home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’94 / [√] Distribution Restricted! / Christian Ruse / Fourier Paper + Apps / nih-image154_source.sea / V1.54 Source / Image.p < prev    next >
Text File  |  1994-02-01  |  70KB  |  2,688 lines

  1. program Image;
  2.  
  3. {NIH Image is a public domain program for the Macintosh for acquiring, }
  4. {enhancing, analyzing, editing, printing, and animating 8-bit images.}
  5.  
  6.  
  7. {Version 1.54, 1 Feb 1994}
  8.  
  9.  
  10. {Developed using Think Pascal 4.0.1}
  11. {Note: requires at least a 5MB partition for Think Pascal.}
  12.  
  13. {Author :}
  14.  
  15. {Wayne Rasband}
  16. {National Institutes of Health}
  17.  
  18. {Internet: wayne@helix.nih.gov}
  19. {Anonymous ftp: zippy.nimh.nih.gov}
  20. {Phone: 301-496-4957}
  21.  
  22.  
  23.     uses
  24.         QuickDraw, Palettes, PrintTraps, Globals, Utilities, Initialization, File1, File2, Analysis, Graphics, {}
  25.         Edit, Filters, Camera, User, Macros1, Macros2, Stacks, Background,  {,UMacroDef, UMacroRun}
  26.         Lut, Projection, Plugins, Text, Math;
  27.  
  28.  
  29. {Turn off automatic toolbox initialization.}
  30. {$I-}
  31.  
  32.  
  33. {PROCEDURE MacsBug; inline $a9ff;}
  34.  
  35.  
  36.     procedure UpdateOptionsMenu;
  37.         var
  38.             CheckIt: boolean;
  39.             i: integer;
  40.     begin
  41.         with info^ do begin
  42.                 CheckItem(OptionsMenuH, GrayscaleItem, (LutMode = Grayscale) or (LutMode = CustomGrayscale));
  43.                 if LutMode <> PseudoColor then
  44.                     ColorTable := CustomTable;
  45.                 CheckItem(ColorTablesMenuH, SystemPaletteItem, ColorTable = AppleDefault);
  46.                 CheckItem(ColorTablesMenuH, Pseudo20Item, ColorTable = Pseudo20);
  47.                 CheckItem(ColorTablesMenuH, Pseudo32Item, ColorTable = Pseudo32);
  48.                 CheckItem(ColorTablesMenuH, RainbowItem, ColorTable = Rainbow);
  49.                 CheckItem(ColorTablesMenuH, Fire1Item, ColorTable = Fire1);
  50.                 CheckItem(ColorTablesMenuH, Fire2Item, ColorTable = Fire2);
  51.                 CheckItem(ColorTablesMenuH, IceItem, ColorTable = Ice);
  52.                 CheckItem(ColorTablesMenuH, GraysItem, ColorTable = Grays);
  53.                 CheckItem(ColorTablesMenuH, SpectrumItem, ColorTable = Spectrum);
  54.                 SetMenuItem(OptionsMenuH, ScaleToFitItem, info <> NoInfo);
  55.                 CheckIt := ScaleToFitWindow;
  56.                 CheckItem(OptionsMenuH, ScaleToFitItem, CheckIt);
  57.                 CheckItem(OptionsMenuH, ThresholdItem, Thresholding);
  58.                 CheckItem(OptionsMenuH, SliceItem, DensitySlicing);
  59.                 SetMenuItem(OptionsMenuH, PropagateItem, nPics > 1);
  60.             end;
  61.     end;
  62.  
  63.  
  64.     procedure UpdateEnhanceMenu;
  65.         var
  66.             ShowItems: boolean;
  67.             i: integer;
  68.             str: str255;
  69.     begin
  70.         ShowItems := Info <> NoInfo;
  71.         for i := SmoothItem to FilterItem do
  72.             SetMenuItem(EnhanceMenuH, i, ShowItems);
  73.         with info^ do
  74.             if (LutMode = GrayScale) or (LutMode = CustomGrayscale) or DensitySlicing then
  75.                 SetItem(EnhanceMenuH, ApplyItem, 'Apply LUT')
  76.             else
  77.                 SetItem(EnhanceMenuH, ApplyItem, 'Convert to Grayscale');
  78.         if CurrentWindow = TextKind then
  79.             SetItem(EnhanceMenuH, ConvolveItem, 'Convolve')
  80.         else
  81.             SetItem(EnhanceMenuH, ConvolveItem, 'Convolve…');
  82.         for i := BinaryItem to FixColorsItem do
  83.             SetMenuItem(EnhanceMenuH, i, ShowItems);
  84.         NumToString(BinaryCount, str);
  85.         str := concat('Set Count[', str, ']…');
  86.         SetItem(BinaryMenuH, SetCountItem, str);
  87.         NumToString(BinaryIterations, str);
  88.         str := concat('Set Iterations[', str, ']…');
  89.         SetItem(BinaryMenuH, IterationsItem, str);
  90.         CheckItem(BackgroundMenuH, FasterItem, FasterBackgroundSubtraction);
  91.         NumToString(BallRadius, str);
  92.         str := concat('Set Radius[', str, ']…');
  93.         SetItem(BackgroundMenuH, RadiusItem, str);
  94.     end;
  95.  
  96.  
  97.  
  98.  
  99.     procedure UpdateSpecialMenu;
  100.         var
  101.             ShowItems: boolean;
  102.     begin
  103.         ShowItems := Info <> NoInfo;
  104.         SetMenuItem(SpecialMenuH, SaveBlankFieldItem, ShowItems);
  105.         SetMenuItem(SpecialMenuH, PhotoModeItem, ShowItems);
  106.         if CurrentWindow = TextKind then
  107.             SetItem(SpecialMenuH, LoadMacrosItem, 'Load Macros from Window')
  108.         else
  109.             SetItem(SpecialMenuH, LoadMacrosItem, 'Load Macros…')
  110.     end;
  111.  
  112.  
  113.     procedure UpdateStacksMenu;
  114.         var
  115.             ShowItems: boolean;
  116.             isStack: boolean;
  117.     begin
  118.         ShowItems := Info <> NoInfo;
  119.         SetMenuItem(StacksMenuH, StackFromWindowsItem, nPics > 0);
  120.         isStack := info^.StackInfo <> nil;
  121.         SetMenuItem(StacksMenuH, WindowsFromStackItem, isStack);
  122.         SetMenuItem(StacksMenuH, AddSliceItem, isStack);
  123.         SetMenuItem(StacksMenuH, DeleteSliceItem, isStack);
  124.         SetMenuItem(StacksMenuH, NextSliceItem, isStack);
  125.         SetMenuItem(StacksMenuH, PreviousSliceItem, isStack);
  126.         SetMenuItem(StacksMenuH, MakeMovieItem, ShowItems);
  127.         SetMenuItem(StacksMenuH, CaptureFramesItem, ShowItems);
  128.         SetMenuItem(StacksMenuH, AnimateItem, isStack);
  129.         SetMenuItem(StacksMenuH, AverageSlicesItem, isStack);
  130.         SetMenuItem(StacksMenuH, MakeMontageItem, isStack);
  131.         SetMenuItem(StacksMenuH, CaptureColorItem, ShowItems);
  132.         SetMenuItem(StacksMenuH, RGBToColorItem, isStack);
  133.         SetMenuItem(StacksMenuH, ColorToRGBItem, ShowItems and (not isStack));
  134.         SetMenuItem(StacksMenuH, RGBToHSVItem, isStack);
  135.         SetMenuItem(StacksMenuH, ProjectItem, isStack);
  136.         SetMenuItem(StacksMenuH, ResliceItem, isStack);
  137.         SetMenuItem(StacksMenuH, ResliceOptionsItem, isStack);
  138.     end;
  139.  
  140.  
  141.     function AboutFilter (d: DialogPtr; var event: EventRecord; var ItemHit: integer): boolean;
  142. { simple filter proc for about box -- must be at top level! % }
  143.     begin
  144.         if (event.what in [MouseDown, KeyDown, AutoKey]) then begin
  145.                 AboutFilter := true;
  146.                 ItemHit := OK;
  147.             end
  148.         else begin
  149.                 AboutFilter := false;
  150.                 ItemHit := 0;
  151.             end;
  152.     end;
  153.  
  154.  
  155.     procedure AboutUProc (d: DialogPtr; item: integer);
  156. { About box user proc -- must be at top level!}
  157.         var
  158.             s: str255;
  159.             saveport: grafptr;
  160.             VersInfo: str255;
  161.     begin
  162.         getport(saveport);
  163.         setport(d);
  164.         if (item = MemItem) then begin
  165.                 NumToString(FreeMem div 1024, s);
  166.                 s := concat(s, 'K free');
  167.                 DrawSItem(MemItem, Geneva, 9, d, s);
  168.             end
  169.         else if (item = VersItem) then begin
  170.                 RealToString(version / 100.0, 4, 2, VersInfo);
  171.                 VersInfo := concat('Version ', VersInfo);
  172.                 DrawSItem(VersItem, Geneva, 9, d, VersInfo);
  173.             end;
  174.         setport(saveport);
  175.     end;
  176.  
  177.  
  178.     procedure DoAbout;
  179.   {About Box by David Powell}
  180.         var
  181.             i: integer;
  182.             d: dialogptr;
  183.             midscreen: point;
  184.             r: rect;
  185.             h: handle;
  186.             itype: integer;
  187.     begin
  188.         d := getnewdialog(AboutID, nil, pointer(-1));
  189.         if (d <> nil) then begin
  190.                 SetPort(d);
  191.                 GetDItem(d, VersItem, itype, h, r);
  192.                 SetDItem(d, VersItem, itype, @AboutUProc, r);
  193.                 GetDItem(d, MemItem, itype, h, r);
  194.                 SetDItem(d, MemItem, itype, @AboutUProc, r);
  195.                 ShowWindow(d);
  196.                 repeat
  197.                     ModalDialog(@aboutfilter, i);
  198.                 until (i = OK);
  199.                 DisposDialog(d);
  200.                 FlushEvents(EveryEvent, 0);
  201.             end;
  202.     end;
  203.  
  204.  
  205.     procedure DoPreferences;
  206.         const
  207.             BufferSizeID = 4;
  208.             ScaleArithmeticID = 6;
  209.             ScaleConvolutionsID = 7;
  210.             InvertValuesID = 8;
  211.             InvertYID = 9;
  212.             LW6ID = 10;
  213.             SwitchingID = 11;
  214.             HighlightID = 12;
  215.             CreatorID = 14;
  216.         var
  217.             mylog: DialogPtr;
  218.             item, i: integer;
  219.             SaveScale, SaveLW6, SaveScaleC: boolean;
  220.             SaveInvertValues, SaveInvertY: boolean;
  221.             SaveBufferSize: LongInt;
  222.             SaveCreator: packed array[1..4] of char;
  223.     begin
  224.         InitCursor;
  225.         SaveBufferSize := BufferSize;
  226.         SaveScale := ScaleArithmetic;
  227.         SaveInvertY := InvertYCoordinates;
  228.         SaveLW6 := DriverHalftoning;
  229.         SaveScaleC := ScaleConvolutions;
  230.         SaveCreator := TextCreator;
  231.         mylog := GetNewDialog(6000, nil, pointer(-1));
  232.         SetDNum(MyLog, BufferSizeID, BufferSize div 1024);
  233.         SetDialogItem(mylog, ScaleArithmeticID, ord(ScaleArithmetic));
  234.         SetDialogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions));
  235.         SetDialogItem(mylog, InvertYID, ord(InvertYCoordinates));
  236.         SetDialogItem(mylog, LW6ID, ord(not DriverHalftoning));
  237.         SetDialogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend));
  238.         SetDialogItem(mylog, HighlightID, ord(HighlightMode));
  239.         SaveInvertValues := InvertPixelValues;
  240.         if InvertPixelValues then
  241.             SetDialogItem(mylog, InvertValuesID, 1);
  242.         SetDString(mylog, CreatorID, TextCreator);
  243.         repeat
  244.             ModalDialog(nil, item);
  245.             if item = BufferSizeID then begin
  246.                     BufferSize := GetDNum(MyLog, BufferSizeID) * 1024;
  247.                     if BufferSize < 1 then begin
  248.                             beep;
  249.                             BufferSize := 1;
  250.                             SetDNum(MyLog, BufferSizeID, BufferSize);
  251.                         end;
  252.                 end;
  253.             if item = ScaleArithmeticID then begin
  254.                     ScaleArithmetic := not ScaleArithmetic;
  255.                     SetDialogItem(mylog, ScaleArithmeticID, ord(ScaleArithmetic));
  256.                     if PasteControl <> nil then
  257.                         DrawPasteControl
  258.                 end;
  259.             if item = ScaleConvolutionsID then begin
  260.                     ScaleConvolutions := not ScaleConvolutions;
  261.                     SetDialogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions));
  262.                 end;
  263.             if item = InvertValuesID then begin
  264.                     InvertPixelValues := not InvertPixelValues;
  265.                     SetDialogItem(mylog, InvertValuesID, ord(InvertPixelValues));
  266.                 end;
  267.             if item = InvertYID then begin
  268.                     InvertYCoordinates := not InvertYCoordinates;
  269.                     SetDialogItem(mylog, InvertYID, ord(InvertYCoordinates));
  270.                 end;
  271.             if item = LW6ID then begin
  272.                     DriverHalftoning := not DriverHalftoning;
  273.                     SetDialogItem(mylog, LW6ID, ord(not DriverHalftoning));
  274.                 end;
  275.             if item = SwitchingID then begin
  276.                     SwitchLUTOnSuspend := not SwitchLUTOnSuspend;
  277.                     SetDialogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend));
  278.                 end;
  279.             if item = HighlightID then begin
  280.                     HighlightMode := not HighlightMode;
  281.                     SetDialogItem(mylog, HighlightID, ord(HighlightMode));
  282.                     LoadLUT(info^.ctable);
  283.                 end;
  284.             if item = CreatorID then
  285.                 TextCreator := GetDString(mylog, item);
  286.         until (item = ok) or (item = cancel);
  287.         DisposDialog(mylog);
  288.         if item = cancel then begin
  289.                 BufferSize := SaveBufferSize;
  290.                 ScaleArithmetic := SaveScale;
  291.                 ScaleConvolutions := SaveScaleC;
  292.                 InvertYCoordinates := SaveInvertY;
  293.                 DriverHalftoning := SaveLW6;
  294.                 if PasteControl <> nil then
  295.                     DrawPasteControl;
  296.                 TextCreator := SaveCreator;
  297.             end
  298.         else
  299.             with info^ do begin
  300.                     if InvertPixelValues and (SaveInvertValues = false) then
  301.                         InvertgrayLevels
  302.                     else if (InvertPixelValues = false) and SaveInvertValues then begin
  303.                             DensityCalibrated := false;
  304.                             DrawLabels('', '', '');
  305.                         end;
  306.                     UpdateTitleBar;
  307.                 end;
  308.         if BufferSize <> SaveBufferSIze then
  309.             PutMessage('You must "Record Preferences" and restart before the Undo and Clipboard buffer size change will take effect.');
  310.     end;
  311.  
  312.  
  313.     procedure UpdateWindowsMenu;
  314.         var
  315.             i, n: integer;
  316.     begin
  317.         for i := NextImageItem to TileImagesItem do
  318.             SetMenuItem(WindowsMenuH, i, nPics > 1);
  319.         for i := SelectToolsItem to SelectResultsItem do
  320.             CheckItem(WindowsMenuH, i, false);
  321.         SetMenuItem(WindowsMenuH, SelectHistogramItem, HistoWindow <> nil);
  322.         SetMenuItem(WindowsMenuH, SelectPlotItem, PlotWindow <> nil);
  323.         SetMenuItem(WindowsMenuH, SelectResultsItem, ResultsWindow <> nil);
  324.         for i := 1 to nTextWindows do
  325.             CheckItem(WindowsMenuH, WindowsMenuItems - 1 + i, false);
  326.         for i := 1 to nPics do
  327.             CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + i, false);
  328.         if PasteControl = nil then
  329.             SetItem(WindowsMenuH, PasteControlItem, 'Show Paste Control')
  330.         else
  331.             SetItem(WindowsMenuH, PasteControlItem, 'Hide Paste Control');
  332.         if CurrentKind < 0 then
  333.             exit(UpdateWindowsMenu); {System Window}
  334.         case CurrentKind of
  335.             ToolKind: 
  336.                 CheckItem(WindowsMenuH, SelectToolsItem, true);
  337.             MapKind: 
  338.                 CheckItem(WindowsMenuH, SelectGrayMapItem, true);
  339.             LUTKind: 
  340.                 CheckItem(WindowsMenuH, SelectLutItem, true);
  341.             ValuesKind: 
  342.                 CheckItem(WindowsMenuH, SelectValuesItem, true);
  343.             HistoKind: 
  344.                 CheckItem(WindowsMenuH, SelectHistogramItem, true);
  345.             ProfilePlotKind, CalibrationPLotKind: 
  346.                 CheckItem(WindowsMenuH, SelectPlotItem, true);
  347.             ResultsKind: 
  348.                 CheckItem(WindowsMenuH, SelectResultsItem, true);
  349.             TextKind:  begin
  350.                     if TextInfo <> nil then
  351.                         CheckItem(WindowsMenuH, WindowsMenuItems - 1 + TextInfo^.WindowNum, true);
  352.                 end;
  353.             PicKind: 
  354.                 CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + info^.PicNum, true);
  355.             otherwise
  356.         end;
  357.     end;
  358.  
  359.  
  360.  
  361.  
  362.     procedure CloseAll;
  363.     FORWARD;
  364.  
  365.  
  366.     procedure DoNew;
  367.         const
  368.             ImageID = 4;
  369.             TextID = 5;
  370.             WidthID = 6;
  371.             HeightID = 7;
  372.             TitleID = 8;
  373.         var
  374.             mylog: DialogPtr;
  375.             item, i: integer;
  376.             SaveWidth, SaveHeight: integer;
  377.             SaveTitle: string[31];
  378.             okay, OpenImage: boolean;
  379.  
  380.         procedure SetButtons;
  381.         begin
  382.             SetDialogItem(mylog, ImageID, ord(OpenImage));
  383.             SetDialogItem(mylog, TextID, ord(not OpenImage));
  384.         end;
  385.  
  386.     begin
  387.         InitCursor;
  388.         OpenImage := true;
  389.         SaveWidth := NewPicWidth;
  390.         SaveHeight := NewPicHeight;
  391.         SaveTitle := NewTitle;
  392.         mylog := GetNewDialog(180, nil, pointer(-1));
  393.         SetButtons;
  394.         SetDNum(MyLog, WidthID, NewPicWidth);
  395.         SelIText(MyLog, WidthID, 0, 32767);
  396.         SetDNum(MyLog, HeightID, NewPicHeight);
  397.         SetDString(MyLog, TitleID, NewTitle);
  398.         repeat
  399.             ModalDialog(nil, item);
  400.             if item = ImageID then begin
  401.                     OpenImage := true;
  402.                     SetButtons;
  403.                 end;
  404.             if item = TextID then begin
  405.                     OpenImage := false;
  406.                     SetButtons;
  407.                 end;
  408.             if item = WidthID then begin
  409.                     NewPicWidth := GetDNum(MyLog, WidthID);
  410.                     if (NewPicWidth < 0) or (NewPicWidth > MaxPicSize) then begin
  411.                             NewPicWidth := SaveWidth;
  412.                             SetDNum(MyLog, WidthID, NewPicWidth);
  413.                         end;
  414.                 end;
  415.             if item = HeightID then begin
  416.                     NewPicHeight := GetDNum(MyLog, HeightID);
  417.                     if (NewPicHeight < 0) or (NewPicHeight > MaxPicSize) then begin
  418.                             NewPicHeight := SaveHeight;
  419.                             SetDNum(MyLog, HeightID, NewPicHeight);
  420.                         end;
  421.                 end;
  422.         until (item = ok) or (item = cancel);
  423.         if item = ok then
  424.             NewTitle := GetDString(MyLog, TitleID);
  425.         DisposDialog(mylog);
  426.         if NewPicWidth < 32 then
  427.             NewPicWidth := 32;
  428.         if odd(NewPicWidth) then
  429.             NewPicWidth := NewPicWidth + 1;
  430.         if NewPicHeight < 16 then
  431.             NewPicHeight := 16;
  432.         if item = cancel then begin
  433.                 NewPicWidth := SaveWidth;
  434.                 NewPicHeight := SaveHeight;
  435.                 NewTitle := SaveTitle;
  436.                 exit(DoNew);
  437.             end;
  438.         if OpenImage then begin
  439.                 okay := NewPicWindow(NewTitle, NewPicWidth, NewPicHeight);
  440.                 if okay then
  441.                     if info^.PixMapSize > UndoBufSize then
  442.                         PutWarning;
  443.             end
  444.         else
  445.             okay := MakeNewTextWindow(NewTitle, 500, 400);
  446.     end;
  447.  
  448.  
  449.     procedure DoMenuEvent (MenuChoice: LongInt);
  450.         var
  451.             MenuID, MenuItem, i, ignore: integer;
  452.             name, str: str255;
  453.             dna, RefNum: integer;
  454.             ItemName: str255;
  455.             FontName: str255;
  456.             ok, isSelection: boolean;
  457.             NewStyle: StyleItem;
  458.             t: FateTable;  {Only needed for MakeSkeleton}
  459.             SaveBFInfo: InfoPtr;
  460.     begin
  461.         MenuID := HiWord(MenuChoice);
  462.         MenuItem := LoWord(MenuChoice);
  463.         case MenuID of
  464.  
  465.             AppleMenu:  begin
  466.                     if MenuItem = 1 then
  467.                         DoAbout
  468.                     else begin
  469.                             GetItem(GetMHandle(AppleMenu), MenuItem, name);
  470.                             ignore := OpenDeskAcc(name)
  471.                         end;
  472.                 end;
  473.  
  474.             FileMenu:  begin
  475.                     StopDigitizing;
  476.                     isInsertionPoint := false;
  477.                     case MenuItem of
  478.                         NewItem: 
  479.                             DoNew;
  480.                         OpenItem: 
  481.                             ok := DoOpen('', 0);
  482.                         ImportItem: 
  483.                             ok := ImportFile('', 0);
  484.             {-}
  485.                         CloseItem: 
  486.                             if OptionKeyWasDown and (CurrentWindow <> TextKInd) then
  487.                                 CloseAll
  488.                             else
  489.                                 DoClose;
  490.                         SaveItem: 
  491.                             if OptionKeyWasDown and (info^.StackInfo = nil) and (CurrentWindow <> TextKind) then
  492.                                 SaveAll
  493.                             else
  494.                                 SaveFile;
  495.                         SaveAsItem: 
  496.                             case CurrentWindow of
  497.                                 TextKind: 
  498.                                     SaveTextAs;
  499.                                 ResultsKind: 
  500.                                     Export('', 0);
  501.                                 otherwise
  502.                                     SaveAs('', 0);
  503.                             end;
  504.                         ExportItem: 
  505.                             Export('', 0);
  506.                         SaveScreenItem: 
  507.                             SaveScreen;
  508.             {-}
  509.                         RecordPreferencesItem: 
  510.                             SaveSettings;
  511.                         RevertItem: 
  512.                             with info^ do
  513.                                 if DataType = EightBits then
  514.                                     RevertToSaved
  515.                                 else
  516.                                     RescaleToEightBits;
  517.                         DuplicateItem: 
  518.                             ok := Duplicate('', false);
  519.                         GetInfoItem: 
  520.                             GetInfo;
  521.        {-}
  522.                         SetHalftoneItem: 
  523.                             SetHalftone;
  524.                         PageSetupItem: 
  525.                             DoPageSetup;
  526.                         PrintItem: 
  527.                             Print(true);
  528.        {-}
  529.                         QuitItem: 
  530.                             finished := true;
  531.                     end;
  532.                 end;
  533.  
  534.             AcquireMenu: 
  535.                 RunAcqPlugIn(MenuItem);
  536.  
  537.             ExportMenu: 
  538.                 RunExportPlugIn(MenuItem);
  539.  
  540.             EditMenu:  begin
  541.                     StopDigitizing;
  542.                     GetItem(GetMHandle(EditMenu), MenuItem, ItemName);
  543.                     if not SystemEdit(MenuItem - 1) then
  544.                         case MenuItem of
  545.                             UndoItem: 
  546.                                 DoUndo;
  547.              {-}
  548.                             CutItem: 
  549.                                 DoCut;
  550.                             CopyItem: 
  551.                                 DoCopy;
  552.                             PasteItem: 
  553.                                 DoPaste;
  554.                             ClearItem: 
  555.                                 DoClear;
  556.             {-}
  557.                             FillItem: 
  558.                                 if CurrentWindow = TextKind then
  559.                                     DoFind
  560.                                 else
  561.                                     SetupOperation(FillItem);
  562.                             InvertItem, DrawBoundaryItem: 
  563.                                 SetupOperation(MenuItem);
  564.                             DrawScaleItem: 
  565.                                 DrawScale;
  566.              {-}
  567.                             SelectAllItem: 
  568.                                 with info^ do
  569.                                     if RoiShowing and EqualRect(RoiRect, PicRect) then
  570.                                         KillRoi
  571.                                     else
  572.                                         SelectAll(true);
  573.                             ScaleAndRotateItem: 
  574.                                 ScaleAndRotate;
  575.               {-}
  576.                             RotateLeftItem: 
  577.                                 Rotate(RotateLeft);
  578.                             RotateRightItem: 
  579.                                 Rotate(RotateRight);
  580.                             FlipVerticalItem: 
  581.                                 FlipOrRotate(FlipVertical);
  582.                             FlipHorizontalItem: 
  583.                                 FlipOrRotate(FlipHorizontal);
  584.               {-}
  585.                             UnzoomItem: 
  586.                                 Unzoom;
  587.                             ShowClipboardItem: 
  588.                                 ShowClipboard;
  589.                         end;
  590.                 end;
  591.  
  592.             OptionsMenu:  begin
  593.                     case MenuItem of
  594.                         GrayscaleItem: 
  595.                             ResetGrayMap;
  596.                         LutOptionsItem: 
  597.                             DoLutOptions;
  598.            {-}
  599.                         PreferencesItem: 
  600.                             DoPreferences;
  601.                         PlotOptionsItem: 
  602.                             DoProfilePlotOptions;
  603.                         ScaleToFitItem: 
  604.                             ScaleToFit;
  605.                         ThresholdItem:  begin
  606.                                 if DensitySlicing then
  607.                                     DisableDensitySlice;
  608.                                 if Info^.Thresholding then
  609.                                     DisableThresholding
  610.                                 else begin
  611.                                         SetupLutUndo;
  612.                                         AutoThreshold;
  613.                                     end;
  614.                             end;
  615.                         SliceItem: 
  616.                             if DensitySlicing then
  617.                                 DisableDensitySlice
  618.                             else begin
  619.                                     if info^.thresholding then
  620.                                         DisableThresholding;
  621.                                     EnableDensitySlice;
  622.                                 end;
  623.                     end;
  624.                 end;
  625.  
  626.             ColorTablesMenu: 
  627.                 SwitchColorTables(MenuItem, true);
  628.  
  629.             FontMenu:  begin
  630.                     GetItem(FontMenuH, MenuItem, FontName);
  631.                     GetFNum(FontName, CurrentFontID);
  632.                     DisplayText(true);
  633.                     if CurrentWindow = TextKind then
  634.                         ChangeFontOrSize;
  635.                 end;
  636.  
  637.             SizeMenu:  begin
  638.                     case MenuItem of
  639.                         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12: 
  640.                             CurrentSize := GetFontSize(MenuItem);
  641.                     end;
  642.                     DisplayText(true);
  643.                     if IsInsertionPoint then
  644.                         UpdatePicWindow;
  645.                     if CurrentWindow = TextKind then
  646.                         ChangeFontOrSize;
  647.                 end;
  648.  
  649.             StyleMenu:  begin
  650.                     case MenuItem of
  651.                         1: 
  652.                             CurrentStyle := [];
  653.                         2, 3, 4, 5, 6:  begin
  654.                                 case MenuItem of
  655.                                     TxBold: 
  656.                                         NewStyle := Bold;
  657.                                     TxItalic: 
  658.                                         NewStyle := Italic;
  659.                                     TxUnderLine: 
  660.                                         NewStyle := Underline;
  661.                                     TxOutLine: 
  662.                                         NewStyle := Outline;
  663.                                     TxShadow: 
  664.                                         NewStyle := Shadow;
  665.                                 end;
  666.                                 if NewStyle in CurrentStyle then
  667.                                     CurrentStyle := CurrentStyle - [NewStyle]
  668.                                 else
  669.                                     CurrentStyle := CurrentStyle + [NewStyle];
  670.                             end;
  671.                         LeftItem: 
  672.                             TextJust := teJustLeft;
  673.                         CenterItem: 
  674.                             TextJust := teJustCenter;
  675.                         RightItem: 
  676.                             TextJust := teJustRight;
  677.                         NoBackgroundItem: 
  678.                             TextBack := NoBack;
  679.                         WithBackgroundItem: 
  680.                             TextBack := WithBack;
  681.                     end; {case}
  682.                     DisplayText(true);
  683.                 end;
  684.  
  685.             PropagateMenu: 
  686.                 DoPropagate(MenuItem);
  687.  
  688.             EnhanceMenu:  begin
  689.                     StopDigitizing;
  690.                     SetupUndo;
  691.                     case MenuItem of
  692.                         SmoothItem: 
  693.                             if OptionKeyDown then
  694.                                 Filter(UnweightedAvg, 0, t)
  695.                             else
  696.                                 Filter(WeightedAvg, 0, t);
  697.                         SharpenItem: 
  698.                             Filter(fsharpen, 0, t);
  699.                         ShadowItem: 
  700.                             Filter(fshadow, 0, t);
  701.                         EdgeDetectItem: 
  702.                             Filter(EdgeDetect, 0, t);
  703.                         ReduceNoiseItem: 
  704.                             Filter(ReduceNoise, 0, t);
  705.                         DitherItem: 
  706.                             Filter(Dither, 0, t);
  707.                         ConvolveItem: 
  708.                             if CurrentWindow = TextKind then
  709.                                 ConvolveUsingText
  710.                             else
  711.                                 Convolve('', 0);
  712.            {-}
  713.                         ImageMathItem: 
  714.                             DoImageMath;
  715.                         ApplyItem: 
  716.                             ApplyLookupTable;
  717.                         EnhanceItem: 
  718.                             EnhanceContrast;
  719.                         EqualizeItem: 
  720.                             EqualizeHistogram;
  721.                         FixColorsItem: 
  722.                             FixColors;
  723.                     end;
  724.                 end;
  725.  
  726.             FilterMenu: 
  727.                 RunFilterPlugin(menuItem);
  728.  
  729.             BinaryMenu: 
  730.                 case MenuItem of
  731.                     MakeBinaryItem: 
  732.                         MakeBinary;
  733.                     ErosionItem: 
  734.                         DoErosion;
  735.                     DilationItem: 
  736.                         DoDilation;
  737.                     OpeningItem: 
  738.                         DoOpening;
  739.                     ClosingItem: 
  740.                         DoClosing;
  741.                     SetCountItem: 
  742.                         SetBinaryCount;
  743.                     IterationsItem: 
  744.                         SetIterations;
  745.                     OutlineItem: 
  746.                         filter(OutlineFilter, 0, t);
  747.                     SkeletonizeItem: 
  748.                         MakeSkeleton;
  749.                 end;
  750.  
  751.             ArithmeticMenu: 
  752.                 DoArithmetic(MenuItem, 0);
  753.  
  754.             BackgroundMenu: 
  755.                 DoBackgroundMenuEvent(MenuItem);
  756.  
  757.             AnalyzeMenu:  begin
  758.                     if MenuItem <> HistogramItem then
  759.                         StopDigitizing;
  760.                     SetupUndo;
  761.                     case MenuItem of
  762.                         MeasureItem: 
  763.                             Measure;
  764.                         AnalyzeItem: 
  765.                             AnalyzeParticles;
  766.                         ShowItem: 
  767.                             ShowResults;
  768.                         OptionsItem: 
  769.                             DoMeasurementOptions;
  770.                         HistogramItem: 
  771.                             DoHistogram;
  772.                         PlotItem: 
  773.                             PlotDensityProfile;
  774.                         PlotSurfaceItem: 
  775.                             PlotSurface;
  776.           {-}
  777.                         SetScaleItem: 
  778.                             SetScale;
  779.                         CalibrateItem: 
  780.                             Calibrate;
  781.                         RedoItem: 
  782.                             RedoMeasurement;
  783.                         DeleteItem: 
  784.                             DeleteMeasurement;
  785.                         ResetItem: 
  786.                             ResetCounter;
  787.                         RestoreItem: 
  788.                             RestoreRoi;
  789.                         MarkItem: 
  790.                             MarkSelection(mCount);
  791.                     end;
  792.                 end;
  793.  
  794.             SpecialMenu:  begin
  795.                     case MenuItem of
  796.                         StartItem: 
  797.                             StartDigitizing;
  798.                         AverageItem: 
  799.                             AverageFrames;
  800.                         SaveBlankFieldItem:  begin
  801.                                 SaveBFInfo := BlankFieldInfo;
  802.                                 BlankFieldInfo := nil; {Prevents shading correction.}
  803.                                 StopDigitizing;
  804.                                 BlankFieldInfo := SaveBFInfo;
  805.                                 SaveBlankField;
  806.                             end;
  807.                         VideoControlItem: 
  808.                             if VideoControl = nil then
  809.                                 ShowVideoControl
  810.                             else
  811.                                 SelectWindow(VideoControl);
  812.                         PhotoModeItem: 
  813.                             PhotoMode;
  814.                         LoadMacrosItem:  begin
  815.                                 LoadMacros;
  816.                                 UnloadSeg(@LoadMacros)
  817.                             end;
  818.                         otherwise
  819.                             if MenuItem >= FirstMacroItem then
  820.                                 RunMacro(MenuItem - FirstMacroItem + 1);
  821.                     end;
  822.                 end;
  823.  
  824.             StacksMenu:  begin
  825.                     StopDigitizing;
  826.                     case MenuItem of
  827.                         StackFromWindowsItem: 
  828.                             MakeStack;
  829.                         WindowsFromStackItem: 
  830.                             MakeWindowsFromStack;
  831.                         AddSliceItem: 
  832.                             ok := AddSlice(true);
  833.                         DeleteSliceItem: 
  834.                             DeleteSlice;
  835.                         NextSliceItem, PreviousSliceItem: 
  836.                             ShowNextSlice(MenuItem);
  837.                         MakeMovieItem: 
  838.                             MakeMovie;
  839.                         CaptureFramesItem: 
  840.                             CaptureFrames;
  841.                         AnimateItem: 
  842.                             Animate;
  843.                         AverageSlicesItem: 
  844.                             AverageSlices;
  845.                         MakeMontageItem: 
  846.                             MakeMontage;
  847.                         CaptureColorItem: 
  848.                             CaptureColor;
  849.                         RGBToColorItem: 
  850.                             ConvertRGBToEightBitColor(false);
  851.                         ColorToRGBItem: 
  852.                             ConvertEightBitColorToRGB;
  853.                         RGBToHSVItem: 
  854.                             ConvertRGBToHSV;
  855.                         ProjectItem: 
  856.                             Project;
  857.                         ResliceItem: 
  858.                             Reslice;
  859.                         ResliceOptionsItem: 
  860.                             DoResliceOptions;
  861.                         otherwise
  862.                             beep
  863.                     end;
  864.                 end;
  865.  
  866.             WindowsMenu:  begin
  867.                     if MenuItem <> PasteControlItem then
  868.                         StopDigitizing;
  869.                     case MenuItem of
  870.                         NextImageItem: 
  871.                             ShowNextImage;
  872.                         StackImagesItem: 
  873.                             StackImages;
  874.                         TileImagesItem: 
  875.                             TileImages;
  876.                         PasteControlItem: 
  877.                             if PasteControl = nil then
  878.                                 ShowPasteControl
  879.                             else
  880.                                 ignore := CloseAWindow(PasteControl);
  881.             {-}
  882.                         SelectToolsItem: 
  883.                             SelectWindow(ToolWindow);
  884.                         SelectGrayMapItem: 
  885.                             SelectWindow(MapWindow);
  886.                         SelectLutItem: 
  887.                             SelectWindow(LUTWindow);
  888.                         SelectValuesItem: 
  889.                             SelectWindow(ValuesWindow);
  890.                         SelectHistogramItem: 
  891.                             if HistoWindow <> nil then
  892.                                 SelectWindow(HistoWindow);
  893.                         SelectPlotItem: 
  894.                             if PlotWindow <> nil then
  895.                                 SelectWindow(PlotWindow);
  896.                         SelectResultsItem: 
  897.                             if ResultsWindow <> nil then
  898.                                 SelectWindow(ResultsWindow);
  899.           {-}
  900.                         otherwise
  901.                             if MenuItem <= (WindowsMenuItems - 1 + nTextWindows) then
  902.                                 SelectWindow(TextWindow[MenuItem - (WindowsMenuItems - 1)])
  903.                             else
  904.                                 SelectWindow(PicWindow[MenuItem - (WindowsMenuItems + nTextWindows)]);
  905.                     end;
  906.                 end;
  907.  
  908.             UserMenu: 
  909.                 DoUserMenuEvent(MenuItem);
  910.             otherwise
  911.         end;
  912.         HiliteMenu(0);
  913.         RoiUpdateTime := 0;
  914.     end;
  915.  
  916.  
  917.     procedure DoFreehand;
  918.         var
  919.             finish: point;
  920.             event: EventRecord;
  921.             wright, wbottom: integer;
  922.             b: boolean;
  923.     begin
  924.         SetPort(info^.wptr);
  925.         PenPat(pat[PatIndex]);
  926.         PenSize(1, 1);
  927.         with info^.wptr^.PortRect do begin
  928.                 wright := right;
  929.                 wbottom := bottom;
  930.             end;
  931.         while Button do begin
  932.                 GetMouse(finish);
  933.                 with finish do begin
  934.                         if h < 0 then
  935.                             h := 0;
  936.                         if v < 0 then
  937.                             v := 0;
  938.                         if h > wright then
  939.                             h := wright;
  940.                         if v > wbottom then
  941.                             v := wbottom;
  942.                         if (xCoordinates^[nCoordinates] <> h) or (yCoordinates^[nCoordinates] <> v) then begin
  943.                                 if nCoordinates < MaxCoordinates then
  944.                                     nCoordinates := nCoordinates + 1
  945.                                 else
  946.                                     beep;
  947.                                 LineTo(h, v);
  948.                                 xCoordinates^[nCoordinates] := h;
  949.                                 yCoordinates^[nCoordinates] := v;
  950.                                 wait(1);
  951.                             end; {if mouse has moved}
  952.                     end; {with}
  953.             end; {while Button}
  954.     end;
  955.  
  956.  
  957.     procedure DoPolygon (start: point);
  958.         var
  959.             Finish, OldFinish: point;
  960.             finished, DoubleClick, done: boolean;
  961.             ticks, MouseUpTime, LastMouseUpTime: LongInt;
  962.             wright, wbottom: integer;
  963.             StartRect: rect;
  964.             MouseDown, MouseUpEvent: boolean;
  965.     begin
  966.         DrawLabels('DX:', 'DY:', 'Length:');
  967.         SetPort(info^.wptr);
  968.         PenMode(PatXor);
  969.         PenSize(1, 1);
  970.         if CurrentTool = PolygonTool then begin
  971.                 Pt2Rect(Start, Start, StartRect);
  972.                 InsetRect(StartRect, -4, -4);
  973.                 FrameRect(StartRect);
  974.             end
  975.         else
  976.             SetRect(StartRect, 0, 0, 0, 0);
  977.         finish := start;
  978.         finished := false;
  979.         with info^.wptr^.PortRect do begin
  980.                 wright := right;
  981.                 wbottom := bottom;
  982.             end;
  983.         MouseUpTime := 0;
  984.         done := false;
  985.         MouseUpEvent := false;
  986.         MouseDown := button;
  987.         repeat
  988.             ShowDxDy(0, 0);
  989.             repeat
  990.                 OldFinish := finish;
  991.                 GetMouse(finish);
  992.                 with finish do begin
  993.                         if h < 0 then begin
  994.                                 h := 0;
  995.                                 done := CurrentTool = LineTool;
  996.                             end;
  997.                         if v < 0 then begin
  998.                                 v := 0;
  999.                                 done := CurrentTool = LineTool;
  1000.                             end;
  1001.                         if h > wright then begin
  1002.                                 h := wright;
  1003.                                 done := CurrentTool = LineTool;
  1004.                             end;
  1005.                         if v > wbottom then begin
  1006.                                 v := wbottom;
  1007.                                 done := CurrentTool = LineTool;
  1008.                             end;
  1009.                     end;
  1010.                 if not EqualPt(finish, OldFinish) then begin
  1011.                         ticks := TickCount;
  1012.                         repeat
  1013.                         until TickCount <> ticks;
  1014.                         MoveTo(start.h, start.v);
  1015.                         LineTo(OldFinish.h, OldFinish.v);
  1016.                         MoveTo(start.h, start.v);
  1017.                         LineTo(finish.h, finish.v);
  1018.                         ShowDxDy(abs(finish.h - start.h), abs(finish.v - start.v));
  1019.                     end;
  1020.                 if button <> MouseDown then begin
  1021.                         MouseUpEvent := not button;
  1022.                         MouseDown := button;
  1023.                     end;
  1024.             until MouseUpEvent;
  1025.             MouseUpEvent := false;
  1026.             LastMouseUpTime := MouseUpTime;
  1027.             MouseUpTime := TickCount;
  1028.             DoubleClick := ((MouseUpTime - LastMouseUpTime) < GetDblTime) and EqualPt(start, finish);
  1029.             if nCoordinates < MaxCoordinates then
  1030.                 nCoordinates := nCoordinates + 1
  1031.             else
  1032.                 beep;
  1033.             xCoordinates^[nCoordinates] := finish.h;
  1034.             yCoordinates^[nCoordinates] := finish.v;
  1035.             start := finish;
  1036.             Finished := (PtInRect(finish, StartRect) or DoubleClick or done) and (nCoordinates > 2);
  1037.         until finished;
  1038.         FlushEvents(EveryEvent, 0);
  1039.     end;
  1040.  
  1041.  
  1042.     procedure MakePolygon (event: EventRecord);
  1043.         var
  1044.             Start: point;
  1045.             i: integer;
  1046.     begin
  1047.         with info^ do begin
  1048.                 start := event.where;
  1049.                 SetPort(wptr);
  1050.                 PenNormal;
  1051.                 xCoordinates^[1] := Start.h;
  1052.                 yCoordinates^[1] := Start.v;
  1053.                 nCoordinates := 1;
  1054.                 MoveTo(start.h, start.v);
  1055.                 case CurrentTool of
  1056.                     FreehandTool:  begin
  1057.                             DoFreehand;
  1058.                             with Start do
  1059.                                 LineTo(h, v);
  1060.                         end;
  1061.                     PolygonTool: 
  1062.                         DoPolygon(start);
  1063.                 end;
  1064.                 if nCoordinates > 2 then begin
  1065.                         ConvertCoordinates;
  1066.                         if CurrentTool = PolygonTool then
  1067.                             MakeOutline(PolygonRoi)
  1068.                         else
  1069.                             MakeOutline(FreehandRoi);
  1070.                     end
  1071.                 else begin
  1072.                         KillRoi;
  1073.                         UpdatePicWindow;
  1074.                     end;
  1075.             end; {with}
  1076.     end;
  1077.  
  1078.  
  1079.     procedure MakeLineRoi (event: EventRecord);
  1080.         var
  1081.             Start: point;
  1082.     begin
  1083.         start := event.where;
  1084.         with Info^ do begin
  1085.                 if PixMapSize > UndoBufSize then begin
  1086.                         beep;
  1087.                         exit(MakeLineRoi);
  1088.                     end;
  1089.                 WhatToUndo := NothingToUndo;
  1090.                 measuring := false;
  1091.                 if LOIType = Straight then begin
  1092.                         DoObject(LineObj, event);
  1093.                         RoiType := LineRoi;
  1094.                         MakeRegion;
  1095.                         RoiShowing := true;
  1096.                         SetupUndo;
  1097.                         exit(MakeLineRoi);
  1098.                     end;
  1099.                 SetPort(wptr);
  1100.                 PenNormal;
  1101.                 MoveTo(start.h, start.v);
  1102.                 xCoordinates^[1] := Start.h;
  1103.                 yCoordinates^[1] := Start.v;
  1104.                 nCoordinates := 1;
  1105.             end; {with info}
  1106.         if LOIType = Freehand then
  1107.             DoFreehand
  1108.         else
  1109.             DoPolygon(start);
  1110.         if nCoordinates > 1 then
  1111.             case LoiType of
  1112.                 freehand: 
  1113.                     MakeNonStraightLineRoi(FreeLineRoi);
  1114.                 segmented: 
  1115.                     MakeNonStraightLineRoi(SegLineRoi);
  1116.             end
  1117.         else
  1118.             with info^ do begin
  1119.                     RoiShowing := false;
  1120.                     RoiType := NoRoi;
  1121.                     UpdatePicWindow;
  1122.                 end;
  1123.     end;
  1124.  
  1125.  
  1126.     procedure DoProfilePlot (event: EventRecord);
  1127.         var
  1128.             ulength, clength: real;
  1129.     begin
  1130.         with Info^ do begin
  1131.                 WhatToUndo := NothingToUndo;
  1132.                 measuring := false;
  1133.                 DoObject(LineObj, event);
  1134.                 RoiType := LineRoi;
  1135.                 MakeRegion;
  1136.                 RoiShowing := true;
  1137.                 SetupUndo;
  1138.                 GetLengthOrPerimeter(ulength, clength);
  1139.                 if ulength > 0 then
  1140.                     PlotDensityProfile
  1141.             end;
  1142.     end;
  1143.  
  1144.  
  1145.     procedure DoMouseDownInWindow (event: EventRecord; WhichWindow: WindowPtr);
  1146.   {Handles mouse down events in the content region of image windows.}
  1147.         var
  1148.             r: rect;
  1149.             str: str255;
  1150.             hloc, vloc: integer;
  1151.             tool: ToolType;
  1152.             start: Point;
  1153.     begin
  1154.         if (WindowPeek(WhichWindow)^.WindowKind <> PicKind) then
  1155.             exit(DoMouseDownInWindow);
  1156.         SetPort(info^.wptr);
  1157.         if Digitizing then
  1158.             if (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) then
  1159.                 StopDigitizing;
  1160.         GlobalToLocal(event.where);
  1161.         IsInsertionPoint := false;
  1162.         with info^ do
  1163.             if RoiShowing then
  1164.                 if EqualRect(RoiRect, PicRect) and (SelectionMode = NewSelection) then {if Select All}
  1165.                     if not (OpPending and (CurrentOp = PasteOp)) then begin
  1166.                             KillRoi;
  1167.                             MouseState := NotInRoi;
  1168.                             exit(DoMouseDownInWindow);
  1169.                         end;
  1170.         if MouseState <> NotInRoi then
  1171.             exit(DoMouseDownInWindow);
  1172.         if SpaceBarDown and (CurrentTool <> TextTool) then
  1173.             tool := grabber
  1174.         else
  1175.             tool := CurrentTool;
  1176.         if (SelectionMode = NewSelection) and not ((tool = MagnifyingGlass) or (tool = Grabber)) then
  1177.             KillRoi;
  1178.         SetupUndo;
  1179.         case tool of
  1180.             SelectionTool: 
  1181.                 DoObject(SelectionRect, event);
  1182.             PolygonTool, FreehandTool: 
  1183.                 MakePolygon(event);
  1184.             OvalSelectionTool: 
  1185.                 DoObject(SelectionOval, event);
  1186.             LineTool: 
  1187.                 MakeLineRoi(event);
  1188.             MagnifyingGlass: 
  1189.                 ZoomIn(event);
  1190.             Grabber: 
  1191.                 Scroll(event);
  1192.             Pencil, Brush, Eraser: 
  1193.                 DoBrush(event);
  1194.             SprayCanTool: 
  1195.                 DoSprayCan;
  1196.             Ruler: 
  1197.                 if OptionKeyDown or ControlKeyDown then
  1198.                     PutMessage('Use the line selection tool and Measure to measure path lengths.')
  1199.                 else begin
  1200.                         DoObject(LineObj, event);
  1201.                         WhatToUndo := UndoEdit;
  1202.                     end;
  1203.             PaintBucket: 
  1204.                 DoFill(event);
  1205.             TextTool: 
  1206.                 DoText(event.where);
  1207.             PlotTool: 
  1208.                 DoProfilePlot(event);
  1209.             PickerTool: 
  1210.                 if BitAnd(Event.modifiers, OptionKey) = OptionKey then
  1211.                     GetBackgroundColor(event)
  1212.                 else
  1213.                     GetForegroundColor(event);
  1214.             CrossHairTool: 
  1215.                 DoPoints(event);
  1216.             AngleTool: 
  1217.                 FindAngle(event);
  1218.             Wand:  begin
  1219.                     if Digitizing then
  1220.                         StopDigitizing;
  1221.                     start := event.where;
  1222.                     ScreenToOffscreen(start);
  1223.                     AutoOutline(start);
  1224.                 end;
  1225.             otherwise
  1226.                 beep;
  1227.         end;
  1228.     end;
  1229.  
  1230.  
  1231.     procedure DoPopupMenusInTools;
  1232.         var
  1233.             Item: integer;
  1234.             ticks: LongInt;
  1235.  
  1236.         procedure DrawCurrentTool;
  1237.         begin
  1238.             InvalRect(ToolRect[CurrentTool]);
  1239.             BeginUpdate(ToolWindow);
  1240.             DrawTools;
  1241.             EndUpdate(ToolWindow);
  1242.         end;
  1243.  
  1244.     begin
  1245.         DrawCurrentTool;
  1246.         ticks := TickCount;
  1247.         repeat
  1248.         until (not button) or (TickCount > ticks + 20);
  1249.         if button and (TickCount > (ticks + 20)) then
  1250.             with ToolRect[CurrentTool] do begin
  1251.                     Item := PopUpMenu(LineToolMenuH, left, top, ord(LOIType) + 1);
  1252.                     case Item of
  1253.                         1: 
  1254.                             LOIType := Straight;
  1255.                         2: 
  1256.                             LOIType := Freehand;
  1257.                         3: 
  1258.                             LOIType := Segmented;
  1259.                         otherwise
  1260.                     end;
  1261.                     DrawCurrentTool;
  1262.                 end;
  1263.     end;
  1264.  
  1265.  
  1266.     procedure DoMouseDownInTools (loc: point);
  1267.  {Handles mouse down events in the tool palette.}
  1268.         var
  1269.             r: rect;
  1270.             OddTool, DoubleClick: boolean;
  1271.             ToolNum, i: integer;
  1272.     begin
  1273.         SetPort(ToolWindow);
  1274.         GlobalToLocal(loc);
  1275.         if loc.v <= StartOfLines then begin
  1276.                 PreviousTool := CurrentTool;
  1277.                 OddTool := loc.h < tmiddle;
  1278.                 ToolNum := (loc.v div tmiddle) * 2;
  1279.                 if not OddTool then
  1280.                     ToolNum := ToolNum + 1;
  1281.                 CurrentTool := ToolType(ToolNum);
  1282.                 isSelectionTool := (CurrentTool = SelectionTool) or (CurrentTool = OvalSelectionTool) or (CurrentTool = PolygonTool) or (CurrentTool = FreehandTool) or (CurrentTool = LineTool);
  1283.                 DoubleClick := (TickCount - ToolTime) < GetDblTime;
  1284.                 ToolTime := TickCount;
  1285.                 InvalRect(ToolRect[CurrentTool]);
  1286.                 InvalRect(ToolRect[PreviousTool]);
  1287.                 IsInsertionPoint := false;
  1288.                 if DoubleClick and (CurrentTool = PreviousTool) then
  1289.                     case CurrentTool of
  1290.                         MagnifyingGlass: 
  1291.                             Unzoom;
  1292.                         SelectionTool:  begin
  1293.                                 StopDigitizing;
  1294.                                 SelectAll(true);
  1295.                             end;
  1296.                         SprayCanTool: 
  1297.                             SetSprayCanSize;
  1298.                         Brush: 
  1299.                             SetBrushSize;
  1300.                         LineTool: 
  1301.                             SetScale;
  1302.                         PolygonTool: 
  1303.                             DoMeasurementOptions;
  1304.                         FreehandTool: 
  1305.                             Calibrate;
  1306.                         ruler: 
  1307.                             SetLineWidth;
  1308.                         PlotTool: 
  1309.                             DoProfilePlotOptions;
  1310.                         Eraser: 
  1311.                             if info <> NoInfo then begin
  1312.                                     KillRoi;
  1313.                                     SetupUndo;
  1314.                                     WhatToUndo := UndoClear;
  1315.                                     StopDigitizing;
  1316.                                     SelectAll(false);
  1317.                                     DoOperation(eraseOp);
  1318.                                 end;
  1319.                         LutTool, Wand: 
  1320.                             if DensitySlicing then
  1321.                                 DisableDensitySlice
  1322.                             else begin
  1323.                                     if Info^.Thresholding then
  1324.                                         ResetGrayMap;
  1325.                                     if OptionKeyDown then
  1326.                                         AutoDensitySlice;
  1327.                                     EnableDensitySlice;
  1328.                                 end;
  1329.                         PickerTool: 
  1330.                             if info^.LutMode <> PseudoColor then begin  {Switch to pseudocolor mode}
  1331.                                     DisableDensitySlice;
  1332.                                     UpdateLUT;
  1333.                                     CurrentTool := LutTool;
  1334.                                     isSelectionTool := false;
  1335.                                     InvalRect(ToolRect[CurrentTool]);
  1336.                                 end
  1337.                             else
  1338.                                 ResetGrayMap;
  1339.                         otherwise
  1340.                     end; {case}
  1341.                 if (not isSelectionTool) and (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) and (CurrentTool <> Wand) then
  1342.                     KillRoi;
  1343.                 if not DoubleClick and (CurrentTool = LineTool) then
  1344.                     KillRoi;
  1345.                 with info^ do
  1346.                     if RoiShowing then
  1347.                         if EqualRect(RoiRect, PicRect) and not isSelectionTool then {if Select All}
  1348.                             KillRoi;
  1349.                 if (CurrentTool = SelectionTool) or (CurrentTool = CrossHairTool) then begin
  1350.                         ValuesMessage := '';
  1351.                         if mCount > 0 then
  1352.                             ShowValues;
  1353.                     end;
  1354.                 RoiMode := MoveMode;
  1355.                 if CurrentTool = LineTool then begin
  1356.                         if Button then
  1357.                             DoPopUpMenusInTools;
  1358.                         if (LoiType = Straight) and (LineWidth <> 1) then begin
  1359.                                 LineWidth := 1;
  1360.                                 UpdateRoiLineWidth;
  1361.                                 ShowLineWidth;
  1362.                             end;
  1363.                     end;
  1364.             end
  1365.         else begin
  1366.                 for i := 1 to nLineTypes do begin
  1367.                         r := lines[i];
  1368.                         with r do begin
  1369.                                 left := left - 13;
  1370.                                 top := top - 2;
  1371.                                 right := right + 2;
  1372.                                 bottom := bottom + 2;
  1373.                             end;
  1374.                         if i = 1 then
  1375.                             with r do
  1376.                                 top := top - 7;
  1377.                         if PtInRect(loc, r) then begin
  1378.                                 with lines[i] do
  1379.                                     LineWidth := bottom - top;
  1380.                                 LineIndex := i;
  1381.                             end;
  1382.                     end;
  1383.                 EraseRect(CheckRect);
  1384.                 InvalRect(CheckRect);
  1385.                 UpdateRoiLineWidth;
  1386.             end;
  1387.     end;
  1388.  
  1389.  
  1390.     procedure ScaleToFitScreen;
  1391.         var
  1392.             trect: rect;
  1393.             ignore: boolean;
  1394.     begin
  1395.         with info^ do begin
  1396.                 MoveWindow(wptr, PicLeftBase, PicTopBase, true);
  1397.                 SetRect(trect, 0, 0, ScreenWidth, ScreenHeight);
  1398.                 ScaleImageWindow(trect);
  1399.                 wrect := trect;
  1400.                 SizeWindow(wptr, trect.right, trect.bottom, true);
  1401.             end;
  1402.     end;
  1403.  
  1404.  
  1405.     procedure DoDrag (WhichWindow: WindowPtr; loc: point);
  1406.         var
  1407.             WinRect, DragBounds, trect: rect;
  1408.             kind: integer;
  1409.     begin
  1410.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1411.         if kind = PicKind then begin
  1412.                 if info^.PictureType = ScionType then
  1413.                     exit(DoDrag);
  1414.                 with info^ do begin  {Save window location}
  1415.                         GetWindowRect(wptr, trect);
  1416.                         savehloc := trect.left;
  1417.                         savevloc := trect.top;
  1418.                     end;
  1419.                 PicLeft := PicLeftBase;
  1420.                 PicTop := PicTopBase;
  1421.             end;
  1422.         DragBounds := ScreenBits.bounds;
  1423.         DragWindow(WhichWindow, loc, DragBounds);
  1424.         if (info^.PictureType = FrameGrabberType) or OptionKeyDown then begin
  1425.                 GetWindowRect(WhichWindow, trect);
  1426.                 MoveWindow(WhichWindow, band(trect.left, $fffc), trect.top, true);
  1427.             end;
  1428.         if WhichWindow = ValuesWindow then
  1429.             ShowValues;
  1430.         if WhichWindow = ResultsWindow then begin
  1431.                 GetWindowRect(WhichWindow, trect);
  1432.                 ResultsTop := trect.top;
  1433.                 ResultsLeft := trect.left;
  1434.             end;
  1435.     end;
  1436.  
  1437.  
  1438.     procedure UpdateMenus;
  1439.     begin
  1440.         OptionKeyWasDown := OptionKeyDown;
  1441.         CurrentKind := CurrentWindow;
  1442.         UpdateFileMenu;
  1443.         UpdateEditMenu;
  1444.         UpdateOptionsMenu;
  1445.         UpdateTextItems;
  1446.         UpdateEnhanceMenu;
  1447.         UpdateAnalysisMenu;
  1448.         UpdateSpecialMenu;
  1449.         UpdateStacksMenu;
  1450.         UpdateWindowsMenu;
  1451.     end;
  1452.  
  1453.  
  1454.     function HMGetBalloons: BOOLEAN;
  1455.     inline
  1456.         $303C, $0003, $A830;
  1457.  
  1458.  
  1459.     function BalloonHelp: boolean;
  1460.     begin
  1461.         if not System7 then begin
  1462.                 BalloonHelp := false;
  1463.                 exit(BalloonHelp);
  1464.             end;
  1465.         BalloonHelp := HMGetBalloons;
  1466.     end;
  1467.  
  1468.  
  1469.     procedure DoMouseDown (event: EventRecord);
  1470.         var
  1471.             WhichWindow: WindowPtr;
  1472.             ThePart, ignore, kind: integer;
  1473.             trect: rect;
  1474.     begin
  1475.         ThePart := FindWindow(event.where, WhichWindow);
  1476.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1477.         case ThePart of
  1478.             InDesk: 
  1479.                 ;
  1480.             InMenuBar:  begin
  1481.                     UpdateMenus;
  1482.                     DoMenuEvent(MenuSelect(event.where));
  1483.                 end;
  1484.             InSysWindow: 
  1485.                 SystemClick(Event, WhichWindow);
  1486.             InContent:  begin
  1487.                     RoiUpdateTime := 0;
  1488.                     if WhichWindow = ToolWindow then begin
  1489.                             if BalloonHelp then
  1490.                                 SelectWindow(ToolWindow);
  1491.                             DoMouseDownInTools(event.where);
  1492.                             exit(DoMouseDown);
  1493.                         end;
  1494.                     if WhichWindow = MapWindow then begin
  1495.                             if BalloonHelp then
  1496.                                 SelectWindow(MapWindow);
  1497.                             DoMouseDownInMap;
  1498.                             exit(DoMouseDown)
  1499.                         end;
  1500.                     if WhichWindow = LUTWindow then begin
  1501.                             if BalloonHelp then
  1502.                                 SelectWindow(LUTWindow);
  1503.                             DoMouseDownInLUT(event);
  1504.                             exit(DoMouseDown)
  1505.                         end;
  1506.                     if WhichWindow = PasteControl then begin
  1507.                             DoMouseDownInPasteControl(event.where);
  1508.                             exit(DoMouseDown)
  1509.                         end;
  1510.                     if WhichWindow = ResultsWindow then begin
  1511.                             DoMouseDownInResults(event.where);
  1512.                             exit(DoMouseDown)
  1513.                         end;
  1514.                     if kind = TextKind then begin
  1515.                             DoMouseDownInText(Event, WhichWindow);
  1516.                             exit(DoMouseDown)
  1517.                         end;
  1518.                     if WhichWindow <> FrontWindow then
  1519.                         SelectWindow(WhichWindow)
  1520.                     else
  1521.                         DoMouseDownInWindow(Event, WhichWindow);
  1522.                 end;
  1523.             InDrag: 
  1524.                 DoDrag(WhichWindow, event.where);
  1525.             InGrow: 
  1526.                 DoGrow(WhichWindow, event);
  1527.             InGoAway: 
  1528.                 if TrackGoAway(WhichWindow, event.where) then
  1529.                     if OptionKeyDown and (kind = PicKind) then
  1530.                         CloseAll
  1531.                     else begin
  1532.                             if WhichWindow <> VideoControl then
  1533.                                 StopDigitizing;
  1534.                             ignore := CloseAWindow(WhichWindow);
  1535.                         end;
  1536.             InZoomIn, InZoomOut: 
  1537.                 with info^ do
  1538.                     case WindowState of
  1539.                         NormalWindow:  begin
  1540.                                 if digitizing then
  1541.                                     exit(DoMouseDown);
  1542.                                 ScaleToFit;
  1543.                                 if ScaleToFitWindow then
  1544.                                     ScaleToFitScreen;
  1545.                             end;
  1546.                         TiledSmall, TiledSmallScaled:  begin
  1547.                                 if WindowState = TiledSmall then begin
  1548.                                         ScaleToFitWindow := true;
  1549.                                         WindowState := TiledBig;
  1550.                                     end
  1551.                                 else
  1552.                                     WindowState := TiledBigScaled;
  1553.                                 savewrect := wrect;
  1554.                                 SaveSrcRect := SrcRect;
  1555.                                 SaveMagnification := magnification;
  1556.                                 GetWindowRect(wptr, trect);
  1557.                                 savehloc := trect.left;
  1558.                                 savevloc := trect.top;
  1559.                                 ScaleToFitScreen;
  1560.                                 UpdatePicWindow;
  1561.                             end;
  1562.                         TiledBig:  begin
  1563.                                 ScaleToFitWindow := false;
  1564.                                 WindowState := TiledSmall;
  1565.                                 wrect := savewrect;
  1566.                                 SrcRect := SaveSrcRect;
  1567.                                 magnification := SaveMagnification;
  1568.                                 HideWindow(wptr);
  1569.                                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1570.                                 MoveWindow(wptr, savehloc, savevloc, true);
  1571.                                 ShowWindow(wptr);
  1572.                                 UpdatePicWindow;
  1573.                                 magnification := 1.0;
  1574.                                 UpdateTitleBar;
  1575.                             end;
  1576.                         TiledBigScaled:  begin
  1577.                                 WindowState := TiledSmallScaled;
  1578.                                 wrect := savewrect;
  1579.                                 SrcRect := PicRect;
  1580.                                 HideWindow(wptr);
  1581.                                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1582.                                 MoveWindow(wptr, savehloc, savevloc, true);
  1583.                                 ShowWindow(wptr);
  1584.                                 UpdatePicWindow;
  1585.                                 if PicRect.right <> 0 then
  1586.                                     magnification := wrect.right / PicRect.right;
  1587.                                 UpdateTitleBar;
  1588.                             end;
  1589.                     end; {case WindowState}
  1590.         end; {case thePart}
  1591.     end;
  1592.  
  1593.  
  1594.     procedure NudgeRoi (key: integer);
  1595.         var
  1596.             dh, dv: integer;
  1597.     begin
  1598.         with info^ do begin
  1599.                 if not RoiShowing then
  1600.                     exit(NudgeRoi);
  1601.                 case key of
  1602.                     LeftArrow:  begin
  1603.                             dh := -1;
  1604.                             dv := 0
  1605.                         end;
  1606.                     RightArrow:  begin
  1607.                             dh := 1;
  1608.                             dv := 0
  1609.                         end;
  1610.                     UpArrow:  begin
  1611.                             dh := 0;
  1612.                             dv := -1
  1613.                         end;
  1614.                     DownArrow:  begin
  1615.                             dh := 0;
  1616.                             dv := 1
  1617.                         end;
  1618.                 end;
  1619.                 if OptionKeyDown then begin
  1620.                         if RoiType = RectRoi then
  1621.                             with RoiRect do begin
  1622.                                     right := right + dh;
  1623.                                     if right < left + 2 then
  1624.                                         right := left + 2;
  1625.                                     bottom := bottom + dv;
  1626.                                     if bottom < top + 2 then
  1627.                                         bottom := top + 2;
  1628.                                     MakeRegion;
  1629.                                 end
  1630.                         else
  1631.                             beep;
  1632.                     end
  1633.                 else begin
  1634.                         OffsetRgn(roiRgn, dh, dv);
  1635.                         RoiRect := roiRgn^^.rgnBBox;
  1636.                     end;
  1637.                 RoiNudged := true;
  1638.                 RoiUpdateTime := 0;
  1639.             end;
  1640.     end;
  1641.  
  1642.  
  1643.     procedure DoKeyDown (event: EventRecord);
  1644.         var
  1645.             ch: char;
  1646.             ich, KeyCode: integer;
  1647.     begin
  1648.         Ch := chr(band(Event.message, CharCodeMask));
  1649.         ich := ord(ch);
  1650. {ShowMessage(long2str(ich));}
  1651.         KeyCode := bsr(band(Event.message, KeyCodeMask), 8);
  1652.         if BitAnd(Event.modifiers, CmdKey) = CmdKey then begin
  1653.                 UpdateMenus;
  1654.                 if OptionKeyWasDown then begin
  1655.                         case KeyCode of
  1656.                             1: 
  1657.                                 ch := 'S';
  1658.                             3: 
  1659.                                 ch := 'F';
  1660.                             5: 
  1661.                                 ch := 'G';
  1662.                             8: 
  1663.                                 ch := 'C';
  1664.                             9: 
  1665.                                 ch := 'V';
  1666.                             13: 
  1667.                                 ch := 'W';
  1668.                             17: 
  1669.                                 ch := 'T';
  1670.                             24: 
  1671.                                 ch := '=';
  1672.                             35: 
  1673.                                 ch := 'P';
  1674.                             44: 
  1675.                                 ch := '/';
  1676.                         end;
  1677.                     end;
  1678.                 DoMenuEvent(MenuKey(Ch));
  1679.                 exit(DoKeyDown)
  1680.             end;
  1681.         if CurrentWindow = TextKind then begin
  1682.                 DoKeyDownInText(ch);
  1683.                 exit(DoKeyDown)
  1684.             end;
  1685.         with info^ do
  1686.             if (CurrentTool = TextTool) and IsInsertionPoint and (ord(ch) <> FunctionKey) then
  1687.                 DrawCharacter(ch)
  1688.             else if ch = BackSpace then
  1689.                 DoClear
  1690.             else if RoiShowing and (ich >= LeftArrow) and (ich <= DownArrow) then
  1691.                 NudgeRoi(ich)
  1692.             else if (StackInfo <> nil) and (ch in ['<', ',', chr(PageUp), '>', '.', chr(PageDown), chr(HomeKey), chr(EndKey)]) then begin
  1693.                     if ch in ['<', ',', chr(PageUp)] then
  1694.                         ShowNextSlice(PreviousSliceItem)
  1695.                     else if ch in ['>', '.', chr(PageDown)] then
  1696.                         ShowNextSlice(NextSliceItem)
  1697.                     else if (ich = HomeKey) or (ich = EndKey) then
  1698.                         ShowFirstOrLastSlice(ich);
  1699.                 end
  1700.             else if nMacros > 0 then
  1701.                 RunKeyMacro(ch, KeyCode);
  1702.     end;
  1703.  
  1704.  
  1705.     procedure DoActivate (event: EventRecord);
  1706.         var
  1707.             WhichWindow: WindowPtr;
  1708.             Activating, SwitchingWindows, isOK: boolean;
  1709.             I, kind: integer;
  1710.             NewInfo: InfoPtr;
  1711.     begin
  1712.         WhichWindow := WindowPtr(event.message);
  1713.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1714.         Activating := odd(event.modifiers);
  1715.         case kind of
  1716.             PicKind:  begin
  1717.                     if Activating then begin
  1718.                             NewInfo := pointer(WindowPeek(WhichWindow)^.RefCon);
  1719.                             SwitchingWindows := NewInfo <> Info;
  1720.                             if SwitchingWindows then begin
  1721.                                     StopDigitizing;
  1722.                                     SaveRoi;
  1723.                                     DisableDensitySlice;
  1724.                                 end;
  1725.                             Info := NewInfo;
  1726.                             if SwitchingWindows then
  1727.                                 ActivateWindow;
  1728.                             Measuring := false;
  1729.                             with info^ do begin
  1730.                                     DrawMap;
  1731.                                     LoadLUT(cTable);
  1732.                                     if digitizing and HighlightSaturatedPixels then
  1733.                                         HighlightPixels;
  1734.                                     GenerateValues;
  1735.                                     if not DensityCalibrated then
  1736.                                         DrawLabels('', '', '');
  1737.                                 end; {with}
  1738.                         end
  1739.                     else
  1740.                         KillOperation; {Deactivate}
  1741.                 end;
  1742.             ResultsKind: 
  1743.                 UpdateResultsWindow;
  1744.             TextKind: 
  1745.                 ActivateTextWindow(WhichWindow, Activating);
  1746.             otherwise
  1747.         end; {case}
  1748.         if not activating then begin
  1749.                 WhichWindow := FrontWindow;
  1750.                 if WhichWindow <> nil then begin
  1751.                         kind := WindowPeek(WhichWindow)^.WindowKind;
  1752.                         if kind < 0 then
  1753.                             ConvertClipboard; {DA has become active}
  1754.                     end;
  1755.             end;
  1756.     end;
  1757.  
  1758.  
  1759.     procedure DoUpdate (event: EventRecord);
  1760.         var
  1761.             WhichWindow: WindowPtr;
  1762.             SaveInfo: InfoPtr;
  1763.             kind: integer;
  1764.     begin
  1765.         WhichWindow := WindowPtr(event.message);
  1766.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1767.         BeginUpdate(WhichWindow);
  1768.         case kind of
  1769.             Pickind:  begin
  1770.                     SaveInfo := info;
  1771.                     Info := pointer(WindowPeek(WhichWindow)^.RefCon);
  1772.                     if not digitizing then begin
  1773.                             UpdatePicWindow;
  1774.                             DrawMyGrowIcon(info^.wptr);
  1775.                         end;
  1776.                     info := SaveInfo;
  1777.                 end;
  1778.             ToolKind: 
  1779.                 DrawTools;
  1780.             MapKind: 
  1781.                 DrawMap;
  1782.             LUTKind: 
  1783.                 DrawLUT;
  1784.             ValuesKind:  begin
  1785.                     DrawLabels('', '', '');
  1786.                     if (mCount > 0) or (ValuesMessage <> '') then
  1787.                         ShowValues;
  1788.                 end;
  1789.             HistoKind: 
  1790.                 DrawHistogram;
  1791.             ProfilePlotKind, CalibrationPlotKind: 
  1792.                 UpdatePlotWindow;
  1793.             ResultsKind: 
  1794.                 UpdateResultsWindow;
  1795.             PasteControlKind: 
  1796.                 DrawPasteControl;
  1797.             TextKind: 
  1798.                 UpdateTextWindow(WhichWindow);
  1799.         end;
  1800.         EndUpdate(WhichWindow);
  1801.     end;
  1802.  
  1803.  
  1804.     procedure DoDiskInsert (event: EventRecord);
  1805. { Process disk insertion event, check for damaged or uninitialized disks. }
  1806.         var
  1807.             p: point;
  1808.             intjunk: integer;
  1809.     begin
  1810.         if (HiWord(event.message) <> NoErr) then begin
  1811.                 DiLoad;
  1812.                 SetPt(p, 100, 80);
  1813.                 intjunk := DiBadMount(p, event.message);
  1814.                 DiUnload;
  1815.             end;
  1816.     end;
  1817.  
  1818.  
  1819.     procedure DoDialogEvent (event: EventRecord);
  1820.   {Handles modeless dialog box events}
  1821.         var
  1822.             isItemHit: boolean;
  1823.             theDialog: DialogPtr;
  1824.             ItemHit: integer;
  1825.             ch: char;
  1826.     begin
  1827.         if (Event.what = KeyDown) and (BitAnd(Event.modifiers, CmdKey) = CmdKey) then begin
  1828.                 UpdateMenus;
  1829.                 ch := chr(band(Event.message, CharCodeMask));
  1830.                 DoMenuEvent(MenuKey(ch));
  1831.                 exit(DoDialogEvent);
  1832.             end;
  1833.         isItemHit := DialogSelect(event, theDialog, ItemHit);
  1834.         if isItemHit and (theDialog = VideoControl) then
  1835.             DoVideoControl(ItemHit);
  1836.     end;
  1837.  
  1838.  
  1839.     function HandleEvents: boolean;
  1840.         const
  1841.             mousemovedmessage = $FA;
  1842.             SuspendResumeMessage = 1;
  1843.             ResumeMask = 1;
  1844.         var
  1845.             Event: EventRecord;
  1846.             result: boolean;
  1847.             theDialog: DialogPtr;
  1848.             ItemHit: integer;
  1849.             SleepTicks: LongInt;
  1850.             okay: boolean;
  1851.     begin
  1852.         if Digitizing then
  1853.             SleepTicks := 0
  1854.         else
  1855.             SleepTicks := 2;
  1856.         if WaitNextEvent(EveryEvent, Event, SleepTicks, nil) then begin
  1857.                 if isDialogEvent(event) then
  1858.                     DoDialogEvent(event)
  1859.                 else
  1860.                     case Event.what of
  1861.                         KeyDown, AutoKey: 
  1862.                             DoKeyDown(Event);
  1863.                         MouseDown: 
  1864.                             DoMouseDown(Event);
  1865.                         ActivateEvt: 
  1866.                             DoActivate(Event);
  1867.                         DiskEvt: 
  1868.                             DoDiskInsert(Event);
  1869.                         UpdateEvt: 
  1870.                             DoUpdate(Event);
  1871.                         app4Evt: 
  1872.                             case BSR(event.message, 24) of
  1873.                                 MouseMovedMessage: 
  1874.                                     ;
  1875.                                 SuspendResumeMessage: 
  1876.                                     if BAND(event.message, ResumeMask) <> 0 then begin{Resume event}
  1877.                                             if SwitchLUTOnSuspend and (WhatToUndo = UndoLUT) then begin
  1878.                                                     UndoLUTChange;
  1879.                                                     WhatToUndo := NothingToUndo;
  1880.                                                 end
  1881.                                             else
  1882.                                                 LoadLUT(info^.ctable);
  1883.                                         end
  1884.                                     else begin {Suspend event}
  1885.                                             KillOperation;
  1886.                                             ConvertClipboard;
  1887.                                             if SwitchLUTOnSuspend then begin
  1888.                                                     SetupLUTUndo;
  1889.                                                     okay := LoadCLUTResource(AppleDefaultCLUT);
  1890.                                                 end;
  1891.                                         end;
  1892.                             end;
  1893.                         otherwise {Do nothing}
  1894.                     end; {case}
  1895.                 HandleEvents := true
  1896.             end
  1897.         else
  1898.             HandleEvents := false;
  1899.     end;
  1900.  
  1901.  
  1902.     procedure ShowInsertionPoint;
  1903.         var
  1904.             tRect: rect;
  1905.             Loc: point;
  1906.             height, imag: integer;
  1907.     begin
  1908.         if (not isInsertionPoint) or (info = NoInfo) then
  1909.             exit(ShowInsertionPoint);
  1910.         if CurrentWindow <> PicKind then
  1911.             exit(ShowInsertionPoint);
  1912.         if (TickCount mod (BlinkTime * 2)) < BlinkTime then
  1913.             exit(ShowInsertionPoint);
  1914.         Loc := InsertionPoint;
  1915.         OffscreenToScreen(loc);
  1916.         with info^, tRect do begin
  1917.                 SetPort(wptr);
  1918.                 imag := trunc(magnification + 0.5);
  1919.                 height := CurrentSize * imag;
  1920.                 height := height - height div 4;
  1921.                 left := loc.h;
  1922.                 bottom := loc.v - imag + 1;
  1923.                 top := bottom - height;
  1924.                 right := left + 1;
  1925.                 PenNormal;
  1926.                 PenSize(imag, imag);
  1927.                 PenMode(PatXor);
  1928.                 FrameRect(tRect);
  1929.                 ticks := TickCount + 3;
  1930.                 repeat
  1931.                 until TickCount > ticks;
  1932.                 FrameRect(tRect);
  1933.             end;
  1934.     end;
  1935.  
  1936.  
  1937.     procedure UndoRoi;
  1938.         var
  1939.             SrcPtr, DstPtr: ptr;
  1940.             offset, ByteCount, tTop, tBottom: LongInt;
  1941.             tRect: rect;
  1942.     begin
  1943.         with info^ do begin
  1944.                 if PixMapSize <> CurrentUndoSize then
  1945.                     exit(UndoRoi);
  1946.                 tRect := RoiRect;
  1947.                 if RoiType = LineRoi then
  1948.                     InsetRect(tRect, -RoiHandleSize, -RoiHandleSize);
  1949.                 with tRect do begin
  1950.                         tTop := top;
  1951.                         tBottom := bottom;
  1952.                         if tTop < 0 then
  1953.                             tTop := 0;
  1954.                         if tTop > PicRect.bottom then
  1955.                             tTop := PicRect.bottom;
  1956.                         if tBottom < 0 then
  1957.                             tBottom := 0;
  1958.                         if tBottom > PicRect.bottom then
  1959.                             tBottom := PicRect.bottom;
  1960.                     end;
  1961.                 offset := tTop * BytesPerRow;
  1962.                 if offset < 0 then
  1963.                     offset := 0;
  1964.                 SrcPtr := ptr(ord4(UndoBuf) + offset);
  1965.                 DstPtr := ptr(ord4(PicBaseAddr) + offset);
  1966.                 ByteCount := (tBottom - tTop) * BytesPerRow;
  1967.                 BlockMove(SrcPtr, DstPtr, ByteCount);
  1968.             end;
  1969.     end;
  1970.  
  1971.  
  1972.     procedure GetLineHandles (var LeftHandle, MiddleHandle, RightHandle: rect);
  1973.         var
  1974.             offset1, offset2, xcenter, ycenter, x1, y1, x2, y2: integer;
  1975.             rx1, ry1, rx2, ry2: real;
  1976.     begin
  1977.         offset1 := RoiHandleSize div 2;
  1978.         offset2 := offset1 + 1;
  1979.         GetLoi(rx1, ry1, rx2, ry2);
  1980.         x1 := trunc(rx1);
  1981.         y1 := trunc(ry1);
  1982.         x2 := trunc(rx2);
  1983.         y2 := trunc(ry2);
  1984.         SetRect(LeftHandle, x1 - offset1, y1 - offset1, x1 + offset2, y1 + offset2);
  1985.         with info^.RoiRect do begin
  1986.                 xcenter := left + (right - left) div 2;
  1987.                 ycenter := top + (bottom - top) div 2;
  1988.             end;
  1989.         SetRect(MiddleHandle, xcenter - offset1, ycenter - offset1, xcenter + offset2, ycenter + offset2);
  1990.         SetRect(RightHandle, x2 - offset1, y2 - offset1, x2 + offset2, y2 + offset2);
  1991.     end;
  1992.  
  1993.  
  1994.     procedure DrawROI;
  1995.         var
  1996.             tRect: rect;
  1997.             RoiHandle, LeftHandle, MiddleHandle, RightHandle: rect;
  1998.             psize: integer;
  1999.             StartTicks: LongInt;
  2000.     begin
  2001.         with Info^ do begin
  2002.                 StartTicks := TickCount;
  2003.                 if OpPending then
  2004.                     DoOperation(CurrentOp);
  2005.                 SetPort(GrafPtr(Info^.osPort));
  2006.                 PenNormal;
  2007.                 if ScaleToFitWindow then
  2008.                     if (magnification < 1.0) and (magnification <> 0.0) then begin
  2009.                             psize := round(1.0 / magnification + 1.5);
  2010.                             PenSize(psize, psize);
  2011.                         end;
  2012.                 if not ((MouseState = DownInRoi) and OpPending) then
  2013.                     if PixMapSize <= UndoBufSize then begin
  2014.                             pmForeColor(BlackIndex);
  2015.                             pmBackColor(WhiteIndex);
  2016.                             case RoiType of
  2017.                                 RectRoi: 
  2018.                                     with RoiRect do begin
  2019.                                             SetRect(RoiHandle, right - RoiHandleSize, bottom - RoiHandleSize, right, bottom);
  2020.                                             if ((right - left) > RoiHandleSize) and ((bottom - top) > RoiHandleSize) then
  2021.                                                 PaintRect(RoiHandle);
  2022.                                         end;
  2023.                                 LineRoi: 
  2024.                                     if Magnification <= 2.0 then begin
  2025.                                             GetLineHandles(LeftHandle, MiddleHandle, RightHandle);
  2026.                                             PaintRect(LeftHandle);
  2027.                                             if LineWidth < 4 then
  2028.                                                 PaintRect(MiddleHandle);
  2029.                                             PaintRect(RightHandle);
  2030.                                             pmForeColor(WhiteIndex);
  2031.                                             FrameRect(LeftHandle);
  2032.                                             if LineWidth < 4 then
  2033.                                                 FrameRect(MiddleHandle);
  2034.                                             FrameRect(RightHandle);
  2035.                                             pmForeColor(BlackIndex);
  2036.                                         end;
  2037.                                 otherwise
  2038.                             end;
  2039.                             PatIndex := (PatIndex + 1) mod 8;
  2040.                             PenPat(pat[PatIndex]);
  2041.                             FrameRgn(roiRgn);
  2042.                             pmForeColor(ForegroundIndex);
  2043.                             pmBackColor(BackgroundIndex);
  2044.                         end;
  2045.                 if PixMapSize > UndoBufSize then begin
  2046.                         if magnification < 1.0 then
  2047.                             PenSize(2, 2);
  2048.                         PatIndex := (PatIndex + 1) mod 8;
  2049.                         PenPat(pat[PatIndex]);
  2050.                         PenMode(PatXor);
  2051.                         FrameRgn(roiRgn);
  2052.                         if MouseState = DownInRoi then begin
  2053.                                 UnionRect(RoiRect, OldRoiRect, tRect);
  2054.                                 UpdateScreen(tRect);
  2055.                             end
  2056.                         else
  2057.                             UpdateScreen(RoiRect);
  2058.                         FrameRgn(roiRgn);
  2059.                     end
  2060.                 else begin
  2061.                         tRect := RoiRect;
  2062.                         if MouseState = DownInRoi then
  2063.                             UnionRect(RoiRect, OldRoiRect, tRect)
  2064.                         else if RoiNudged then begin
  2065.                                 tRect := RoiRect;
  2066.                                 RoiNudged := false;
  2067.                             end;
  2068.                         if RoiType = LineRoi then
  2069.                             InsetRect(tRect, -RoiHandleSize * 2, -RoiHandleSize * 2)
  2070.                         else
  2071.                             InsetRect(tRect, -2, -2);
  2072.                         UpdateScreen(tRect);
  2073.                         UndoRoi;  {Erase offscreen ROI}
  2074.                     end;
  2075.                 RoiUpdateTime := TickCount - StartTicks;
  2076.             end; {with}
  2077.     end;
  2078.  
  2079.  
  2080.     procedure MoveLineEndPoint (osloc: point);
  2081.         var
  2082.             deltax, deltay: real;
  2083.     begin
  2084.         with info^, osloc, info^.RoiRect do begin
  2085.                 if h < 0 then
  2086.                     h := 0;
  2087.                 if h > PicRect.right then
  2088.                     h := PicRect.right;
  2089.                 if v < 0 then
  2090.                     v := 0;
  2091.                 if v > PicRect.bottom then
  2092.                     v := PicRect.bottom;
  2093.                 if RoiMode = LeftEndMode then begin
  2094.                         LX1 := h;
  2095.                         LY1 := v;
  2096.                         LX2 := left + LX2;
  2097.                         LY2 := top + LY2;
  2098.                     end
  2099.                 else begin
  2100.                         LX2 := h;
  2101.                         LY2 := v;
  2102.                         LX1 := left + LX1;
  2103.                         LY1 := top + LY1;
  2104.                     end;
  2105.                 if ShiftKeyDown then begin
  2106.                         deltax := LX2 - LX1;
  2107.                         deltay := LY2 - LY1;
  2108.                         if abs(deltax) > abs(deltay) then begin
  2109.                                 if RoiMode = LeftEndMode then
  2110.                                     LY2 := LY1
  2111.                                 else
  2112.                                     LY1 := LY2
  2113.                             end
  2114.                         else begin
  2115.                                 if RoiMode = LeftEndMode then
  2116.                                     LX2 := LX1
  2117.                                 else
  2118.                                     LX1 := LX2
  2119.                             end;
  2120.                     end; {if ShiftKeyDown}
  2121.                 MakeRegion;
  2122.                 osMouseDownLoc := osloc;
  2123.                 RoiUpdateTime := 0;
  2124.                 Show3Values(h, v, MyGetPixel(h, v));
  2125.             end;
  2126.     end;
  2127.  
  2128.  
  2129.     procedure MoveRoi (osloc: point);
  2130.         var
  2131.             dh, dv: integer;
  2132.     begin
  2133.         with info^, info^.RoiRect, osloc do begin
  2134.                 dh := h - osMouseDownLoc.h;
  2135.                 dv := v - osMouseDownLoc.v;
  2136.                 OldRoiRect := RoiRect;
  2137.                 if RoiType = LineRoi then
  2138.                     if (RoiMode = LeftEndMode) or (RoiMode = RightEndMode) then begin
  2139.                             MoveLineEndPoint(osloc);
  2140.                             exit(MoveRoi);
  2141.                         end;
  2142.                 if RoiMode = MoveMode then begin
  2143.                         if RoiMovementState = Constrained then begin
  2144.                                 if dv <> 0 then
  2145.                                     RoiMovementState := ConstrainedV
  2146.                                 else if dh <> 0 then
  2147.                                     RoiMovementState := ConstrainedH
  2148.                             end;
  2149.                         if RoiMovementState = ConstrainedH then
  2150.                             dv := 0
  2151.                         else if RoiMovementState = ConstrainedV then
  2152.                             dh := 0;
  2153.                         if not OpPending then begin
  2154.                                 if left + dh < 0 then
  2155.                                     dh := -left;
  2156.                                 if top + dv < 0 then
  2157.                                     dv := -top;
  2158.                             end;
  2159.                     end;
  2160.                 if not OpPending then begin
  2161.                         if right + dh > PicRect.right then
  2162.                             dh := PicRect.right - right;
  2163.                         if bottom + dv > PicRect.bottom then
  2164.                             dv := PicRect.bottom - bottom;
  2165.                     end;
  2166.                 if RoiMode = StretchMode then begin
  2167.                         measuring := false;
  2168.                         DrawLabels('Width:', 'Height:', '');
  2169.                         if h > left then begin
  2170.                                 right := right + dh;
  2171.                                 if right < (left + 1) then
  2172.                                     right := left + 1;
  2173.                                 if (right - h) > 5 then
  2174.                                     right := h + 2;
  2175.                             end
  2176.                         else
  2177.                             right := left + 1;
  2178.                         if v > top then begin
  2179.                                 bottom := bottom + dv;
  2180.                                 if bottom < (top + 1) then
  2181.                                     bottom := top + 1;
  2182.                                 if (bottom - v) > 5 then
  2183.                                     bottom := v + 2;
  2184.                             end
  2185.                         else
  2186.                             bottom := top + 1;
  2187.                         Show3Values(right - left, bottom - top, -1);
  2188.                         MakeRegion;
  2189.                     end
  2190.                 else begin
  2191.                         OffsetRgn(roiRgn, dh, dv);
  2192.                         Show3Values(left, top, MyGetPixel(left, top));
  2193.                     end;
  2194.                 RoiRect := roiRgn^^.rgnBBox;
  2195.                 osMouseDownLoc := osloc;
  2196.                 RoiUpdateTime := 0; {Forces ROI outline to be redrawn}
  2197.             end; {with Info}
  2198.     end;
  2199.  
  2200.  
  2201.     procedure ShowHistogramValues (GrayLevel: LongInt);
  2202.         var
  2203.             hstart, vstart, ivalue: integer;
  2204.     begin
  2205.         hstart := ValuesHStart;
  2206.         vstart := ValuesVStart;
  2207.         SetPort(ValuesWindow);
  2208.         TextSize(9);
  2209.         TextFont(Monaco);
  2210.         TextMode(SrcCopy);
  2211.         MoveTo(xValueLoc, vstart);
  2212.         with info^ do
  2213.             if DensityCalibrated then begin
  2214.                     if InvertingCalibrationFunction then
  2215.                         DrawReal(cvalue[255 - GrayLevel], 8, 2)
  2216.                     else
  2217.                         DrawReal(cvalue[GrayLevel], 8, 2);
  2218.                     DrawString(' (');
  2219.                     DrawLong(GrayLevel);
  2220.                     DrawString(' )');
  2221.                 end
  2222.             else
  2223.                 DrawLong(GrayLevel);
  2224.         DrawString('          ');
  2225.         MoveTo(yValueLoc, vstart + 10);
  2226.         if InvertingCalibrationFunction then
  2227.             DrawLong(histogram[255 - GrayLevel])
  2228.         else
  2229.             DrawLong(histogram[GrayLevel]);
  2230.         DrawString('          ');
  2231.     end;
  2232.  
  2233.  
  2234.     procedure DoPlotCursor (loc: point; kind: integer);
  2235.         var
  2236.             xscale, angle: extended;
  2237.             xvalue, xinc, yinc: integer;
  2238.             pt: point;
  2239.     begin
  2240.         DrawLabels('X:', 'Y:', '');
  2241.         SetCursor(ToolCursor[SelectionTool]);
  2242.         SetPort(PlotWindow);
  2243.         GlobalToLocal(loc);
  2244.         xscale := PlotCount / (PlotWidth - PlotRightMargin - PlotLeftMargin);
  2245.         xvalue := trunc((loc.h - PlotLeftMargin) * xscale);
  2246.         if (xvalue < 0) or (xvalue >= PlotCount) then
  2247.             exit(DoPlotCursor);
  2248.         Show2PlotValues(xvalue, PlotData^[xvalue]);
  2249.         if (kind = CalibrationPlotKind) or (info^.RoiType <> LineRoi) then
  2250.             exit(DoPlotCursor);
  2251.         if button and (info <> NoInfo) then
  2252.             with loc do begin
  2253.                     SetPort(info^.wptr);
  2254.                     PenMode(PatXor);
  2255.                     PenSize(1, 1);
  2256.                     angle := (PlotAngle / 180.0) * pi;
  2257.                     xinc := round(cos(angle) * xvalue);
  2258.                     yinc := round(-sin(angle) * xvalue);
  2259.                     h := PlotStart.h + xinc;
  2260.                     v := PlotStart.v + yinc;
  2261.                     OffscreenToScreen(loc);
  2262.                     MoveTo(h - 7, v);
  2263.                     LineTo(h + 7, v);
  2264.                     MoveTo(h, v - 7);
  2265.                     LineTo(h, v + 7);
  2266.                     wait(2);
  2267.                     MoveTo(h - 7, v);
  2268.                     LineTo(h + 7, v);
  2269.                     MoveTo(h, v - 7);
  2270.                     LineTo(h, v + 7);
  2271.                 end;
  2272.     end;
  2273.  
  2274.  
  2275.     procedure SelectCursor;
  2276.         var
  2277.             loc, osloc, gloc: point;
  2278.             where, kind, i, color, x, y, margin: integer;
  2279.             WhichWindow: WindowPtr;
  2280.             MouseInRoi: boolean;
  2281.             fwptr: WindowPtr;
  2282.             CalValue: extended;
  2283.             RoiStretchHandle, LeftHandle, MiddleHandle, RightHandle: rect;
  2284.             MovingRoi: boolean;
  2285.             pvalue: integer;
  2286.     begin
  2287.         if PasteControl <> nil then begin
  2288.                 fwptr := FrontWindow;
  2289.                 if fwptr <> nil then
  2290.                     if WindowPeek(fwptr)^.WindowKind <> PasteControlKind then
  2291.                         BringToFront(PasteControl);
  2292.             end;
  2293.         SetPort(ScreenPort);
  2294.         GetMouse(gloc);
  2295.         loc := gloc;
  2296.         where := FindWindow(gloc, WhichWindow);
  2297.         if WhichWindow = nil then begin
  2298.                 InitCursor;
  2299.                 exit(SelectCursor)
  2300.             end;
  2301.         kind := WindowPeek(WhichWindow)^.WindowKind;
  2302.         if kind < 0 then
  2303.             exit(SelectCursor); {System Window}
  2304.         if where <> InContent then begin
  2305.                 InitCursor;
  2306.                 exit(SelectCursor)
  2307.             end;
  2308.         case kind of
  2309.             PicKind:  begin
  2310.                     if Info = NoInfo then begin
  2311.                             InitCursor;
  2312.                             exit(SelectCursor)
  2313.                         end;
  2314.                     SetPort(info^.wptr);
  2315.                     GlobalToLocal(loc);
  2316.                     osloc := loc;
  2317.                     ScreenToOffscreen(osloc);
  2318.                     MovingRoi := false;
  2319.                     with info^ do begin
  2320.                             SelectionMode := NewSelection;
  2321.                             if RoiShowing and ((isSelectionTool) or (CurrentTool = Wand)) and (currentTool <> LineTool) then begin
  2322.                                     if OptionKeyDown then
  2323.                                         SelectionMode := SubSelection
  2324.                                     else if ControlKeyDown or (ShiftKeyDown and (CurrentTool <> OvalSelectionTool) and (CurrentTool <> SelectionTool)) then
  2325.                                         SelectionMode := AddSelection;
  2326.                                 end;
  2327.                             if RoiShowing and (SelectionMode = NewSelection) then begin
  2328.                                     MouseInRoi := PtInRgn(osloc, roiRgn);
  2329.                                     if RoiType = LineRoi then begin
  2330.                                             GetLineHandles(LeftHandle, MiddleHandle, RightHandle);
  2331.                                             if magnification <= 2.0 then begin
  2332.                                                     InsetRect(LeftHandle, -2, -2);
  2333.                                                     InsetRect(MiddleHandle, -2, -2);
  2334.                                                     InsetRect(RightHandle, -2, -2);
  2335.                                                 end;
  2336.                                             MouseInRoi := MouseInRoi or PtInRect(osloc, LeftHandle) or MouseInRoi or PtInRect(osloc, MiddleHandle) or MouseInRoi or PtInRect(osloc, RightHandle);
  2337.                                         end;
  2338.                                 end
  2339.                             else
  2340.                                 MouseInRoi := false
  2341.                         end; {with}
  2342.                     if MouseInRoi or (MouseState = DownInRoi) then begin
  2343.                             if MouseState = NotInRoi then
  2344.                                 MouseState := InRoi;
  2345.                             InitCursor;
  2346.                             if button then begin
  2347.                                     if MouseState = InRoi then begin
  2348.                                             if OpPending and (CurrentOp <> PasteOp) then
  2349.                                                 SetupUndo;
  2350.                                             MouseState := DownInRoi;
  2351.                                             osMouseDownLoc := osloc;
  2352.                                             with info^ do
  2353.                                                 case RoiType of
  2354.                                                     RectRoi:  begin
  2355.                                                             if magnification > 1.0 then
  2356.                                                                 margin := 0
  2357.                                                             else
  2358.                                                                 margin := 2;
  2359.                                                             with RoiRect do
  2360.                                                                 SetRect(RoiStretchHandle, right - RoiHandleSize - margin, bottom - RoiHandleSize - margin, right, bottom);
  2361.                                                             if PtInRect(osloc, RoiStretchHandle) then
  2362.                                                                 RoiMode := StretchMode
  2363.                                                             else
  2364.                                                                 RoiMode := MoveMode;
  2365.                                                         end;
  2366.                                                     LineRoi: 
  2367.                                                         if PtInRect(osloc, LeftHandle) then
  2368.                                                             RoiMode := LeftEndMode
  2369.                                                         else if PtInRect(osloc, RightHandle) then
  2370.                                                             RoiMode := RightEndMode
  2371.                                                         else
  2372.                                                             RoiMode := MoveMode;
  2373.                                                     otherwise
  2374.                                                 end; {case}
  2375.                                             if ShiftKeyDown then
  2376.                                                 RoiMovementState := Constrained
  2377.                                             else
  2378.                                                 RoiMovementState := Unconstrained;
  2379.                                         end;
  2380.                                     MoveRoi(osloc);
  2381.                                     MovingRoi := true;
  2382.                                 end
  2383.                             else
  2384.                                 MouseState := InRoi
  2385.                         end
  2386.                     else begin
  2387.                             MouseState := NotInRoi;
  2388.                             if SpaceBarDown and (CurrentTool <> TextTool) then
  2389.                                 SetCursor(ToolCursor[Grabber])
  2390.                             else if (SelectionMode = AddSelection) and (CurrentTool = Wand) then
  2391.                                 SetCursor(WandPlusCursor)
  2392.                             else if (SelectionMode = SubSelection) and (CurrentTool = Wand) then
  2393.                                 SetCursor(WandMinusCursor)
  2394.                             else if SelectionMode = AddSelection then
  2395.                                 SetCursor(CrossPlusCursor)
  2396.                             else if SelectionMode = SubSelection then
  2397.                                 SetCursor(CrossMinusCursor)
  2398.                             else if (CurrentTool = MagnifyingGlass) and OptionKeyDown then
  2399.                                 SetCursor(GlassMinusCursor)
  2400.                             else
  2401.                                 SetCursor(ToolCursor[CurrentTool]);
  2402.                         end;
  2403.                     if not MovingRoi then begin
  2404.                             if CurrentTool = PickerTool then
  2405.                                 DrawLabels('X:', 'Y:', 'RGB:')
  2406.                             else
  2407.                                 DrawLabels('X:', 'Y:', 'Value:');
  2408.                             with osloc do begin
  2409.                                     if Digitizing then
  2410.                                         pvalue := GetFGPixel(h, v)
  2411.                                     else
  2412.                                         pvalue := MyGetPixel(h, v);
  2413.                                     Show3Values(h, v, pvalue);
  2414.                                 end;
  2415.                         end;
  2416.                 end;
  2417.             HistoKind:  begin
  2418.                     DrawLabels('Level:', 'Count:', '');
  2419.                     SetCursor(ToolCursor[SelectionTool]);
  2420.                     SetPort(HistoWindow);
  2421.                     GlobalToLocal(loc);
  2422.                     ShowHistogramValues(loc.h);
  2423.                 end;
  2424.             ProfilePlotKind, CalibrationPlotKind: 
  2425.                 DoPlotCursor(loc, kind);
  2426.             LUTKind:  begin
  2427.                     if info^.DensityCalibrated then
  2428.                         DrawLabels('Index:', 'Value:', '  RGB:')
  2429.                     else
  2430.                         DrawLabels('Index:', '  RGB:', '');
  2431.                     SetPort(LUTWindow);
  2432.                     GlobalToLocal(loc);
  2433.                     if (CurrentTool = LutTool) or (CurrentTool = Wand) then begin
  2434.                             if loc.v < 256 then
  2435.                                 SetCursor(LUTCursor)
  2436.                             else
  2437.                                 InitCursor
  2438.                         end
  2439.                     else
  2440.                         SetCursor(PickerCursor);
  2441.                     if loc.v < 256 then begin
  2442.                             ShowRGBValues(loc.v);
  2443.                         end
  2444.                     else begin
  2445.                             color := 0;
  2446.                             for i := 1 to nExtraColors + 2 do
  2447.                                 if PtInRect(loc, ExtraColorsRect[i]) then
  2448.                                     Color := ExtraColorsEntry[i];
  2449.                             ShowRGBValues(color);
  2450.                         end;
  2451.                 end;
  2452.             MapKind: 
  2453.                 if OptionKeyDown then
  2454.                     SetCursor(ToolCursor[SelectionTool])
  2455.                 else
  2456.                     SetCursor(gmCursor);
  2457.             TextKind:  begin
  2458.                     TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  2459.                     if TextInfo <> nil then
  2460.                         with TextInfo^ do begin
  2461.                                 SetPort(TextWindowPtr);
  2462.                                 GlobalToLocal(loc);
  2463.                                 TEIdle(TextTE);
  2464.                                 with TextWindowPtr^.portRect do begin
  2465.                                         if (loc.h < (right - ScrollBarWidth)) and (loc.v < (bottom - ScrollBarWidth)) then
  2466.                                             SetCursor(ToolCursor[TextTool])
  2467.                                         else
  2468.                                             InitCursor;
  2469.                                     end;
  2470.                             end;
  2471.                 end;
  2472.             otherwise
  2473.                 InitCursor;
  2474.         end; {case}
  2475.     end;
  2476.  
  2477.  
  2478.     procedure CloseAll;
  2479.         var
  2480.             i, j, result: integer;
  2481.             WPeek, NextWPeek: WindowPeek;
  2482.             ignore: boolean;
  2483.     begin
  2484.         InitCursor;
  2485.         WPeek := WindowPeek(FrontWindow);
  2486.         StopDigitizing;
  2487.         while wpeek <> nil do begin
  2488.                 NextWPeek := WPeek^.NextWindow;
  2489.                 case wPeek^.WindowKind of
  2490.                     PicKind:  begin
  2491.                             Info := pointer(WPeek^.RefCon);
  2492.                             result := CloseAWindow(info^.wptr);
  2493.                             if not CommandPeriod then
  2494.                                 for j := 1 to 2 do
  2495.                                     ignore := HandleEvents;
  2496.                             if result = cancel then begin
  2497.                                     ActivateWindow;
  2498.                                     finished := false;
  2499.                                     exit(CloseAll)
  2500.                                 end;
  2501.                         end;
  2502.                     TextKind:  begin
  2503.                             result := CloseAWindow(WindowPtr(wPeek));
  2504.                             if result = cancel then begin
  2505.                                     finished := false;
  2506.                                     exit(CloseAll)
  2507.                                 end;
  2508.                         end;
  2509.                     otherwise
  2510.                         ;
  2511.                 end; {case}
  2512.                 wpeek := NextWPeek;
  2513.             end;
  2514.     end;
  2515.  
  2516.  
  2517.     procedure DoStartup;
  2518.   {Process Finder startup information}
  2519.         var
  2520.             message, ndocs, err, i, j: integer;
  2521.             DocInfo: AppFile;
  2522.             DefaultPalette, OpenedOK: boolean;
  2523.             PaletteName, OutlineName: str255;
  2524.             PaletteFile, OutlineFile: boolean;
  2525.             ignore, PrintDocs: boolean;
  2526.  
  2527.         procedure PrintDocument;
  2528.             var
  2529.                 i: integer;
  2530.         begin
  2531.             WhatToPrint := PrintImage;
  2532.             if PrintOptionsSet then
  2533.                 Print(false)
  2534.             else begin
  2535.                     Print(true);
  2536.                     PrintOptionsSet := true
  2537.                 end;
  2538.             DoClose;
  2539.             for i := 1 to 10 do
  2540.                 ignore := HandleEvents;
  2541.         end;
  2542.  
  2543.     begin
  2544.         for j := 1 to 10 do
  2545.             ignore := HandleEvents;
  2546.         PrintOptionsSet := false;
  2547.         PaletteFile := false;
  2548.         OutlineFile := false;
  2549.         CountAppFiles(message, ndocs);
  2550.         PrintDocs := message = appPrint;
  2551.         if ndocs >= 1 then
  2552.             for i := 1 to ndocs do begin
  2553.                     GetAppFiles(i, DocInfo);
  2554.                     with DocInfo do begin
  2555.                             if ftype = 'ICOL' then begin
  2556.                                     PaletteFile := true;
  2557.                                     PaletteName := docinfo.fname;
  2558.                                     ClrAppFiles(i)
  2559.                                 end;
  2560.                             if fType = 'IPIC' then begin
  2561.                                     WhatToOpen := OpenImage;
  2562.                                     OpenedOK := OpenFile(fName, vRefNum);
  2563.                                     for j := 1 to 10 do
  2564.                                         ignore := HandleEvents;
  2565.                                     ClrAppFiles(i);
  2566.                                     if not OpenedOK then
  2567.                                         exit(DoStartup);
  2568.                                     if PrintDocs then
  2569.                                         PrintDocument;
  2570.                                 end;
  2571.                             if fType = 'TIFF' then begin
  2572.                                     WhatToOpen := OpenTIFF;
  2573.                                     OpenedOK := OpenFile(fName, vRefNum);
  2574.                                     for j := 1 to 10 do
  2575.                                         ignore := HandleEvents;
  2576.                                     ClrAppFiles(i);
  2577.                                     if not OpenedOK then
  2578.                                         exit(DoStartup);
  2579.                                     if PrintDocs then
  2580.                                         PrintDocument;
  2581.                                 end;
  2582.                             if fType = 'PICT' then begin
  2583.                                     OpenedOK := OpenPICT(fName, vRefNum, false);
  2584.                                     for j := 1 to 10 do
  2585.                                         ignore := HandleEvents;
  2586.                                     ClrAppFiles(i);
  2587.                                     if not OpenedOK then
  2588.                                         exit(DoStartup);
  2589.                                     if PrintDocs then
  2590.                                         PrintDocument;
  2591.                                 end;
  2592.                             if fType = 'PICS' then begin
  2593.                                     OpenedOK := OpenPICS(fName, vRefNum);
  2594.                                     for j := 1 to 10 do
  2595.                                         ignore := HandleEvents;
  2596.                                     ClrAppFiles(i);
  2597.                                     if not OpenedOK then
  2598.                                         exit(DoStartup);
  2599.                                 end;
  2600.                             if ftype = 'Iout' then begin
  2601.                                     OutlineFile := true;
  2602.                                     OutlineName := docinfo.fname;
  2603.                                     ClrAppFiles(i)
  2604.                                 end;
  2605.                             if fType = 'TEXT' then begin
  2606.                                     OpenedOK := OpenTextFile(fName, vRefNum);
  2607.                                     ClrAppFiles(i);
  2608.                                     if not OpenedOK then
  2609.                                         exit(DoStartup);
  2610.                                 end;
  2611.                         end; {with}
  2612.                 end;
  2613.         if PaletteFile then
  2614.             OpenColorTable(PaletteName, DocInfo.vRefNum);
  2615.         if OutlineFile then
  2616.             OpenOutline(OutlineName, DocInfo.vRefNum);
  2617.     end;
  2618.  
  2619.  
  2620.     procedure LoadDefaultMacros;
  2621.   {Looks for a text file named "Image Macros" in the same folder as}
  2622.   {Image, and, if found,  loads the macros contained in it.}
  2623.         var
  2624.             err: OSErr;
  2625.             LaunchRefNum: integer;
  2626.             FinderInfo: FInfo;
  2627.             id: LongInt;
  2628.     begin
  2629.         err := GetVol(nil, LaunchRefNum);
  2630.         if err = noerr then
  2631.             err := GetFInfo('Image Macros', LaunchRefNum, FinderInfo);
  2632.         if err = NoErr then begin
  2633.                 LoadMacrosFromFile('Image Macros', LaunchRefNum);
  2634.                 UnloadSeg(@LoadMacros);
  2635.             end;
  2636.     end;
  2637.  
  2638.  
  2639.     procedure Shutdown;
  2640.         var
  2641.             AlertID: integer;
  2642.     begin
  2643.         if (UnsavedResults and (mCount > 10)) or (UnsavedResults and (ResultsWindow <> nil)) then begin
  2644.                 InitCursor;
  2645.                 AlertID := alert(500, nil);
  2646.                 if AlertID = CancelResetID then begin
  2647.                         finished := false;
  2648.                         exit(Shutdown)
  2649.                     end;
  2650.             end;
  2651.         CloseAll;
  2652.         if finished then
  2653.             ConvertClipboard;
  2654.     end;
  2655.  
  2656.  
  2657. begin
  2658.     Init;
  2659.   {InitUserMacros;}
  2660.     SetupMenus;
  2661.     GetSettings;
  2662.     AllocateBuffers;
  2663.     AllocateArrays;
  2664.     ConvertSystemClipboard;
  2665.     DoStartup;
  2666.     LoadDefaultMacros;
  2667.     FindPlugIns;
  2668.     UnloadSeg(@Init);
  2669. {InitUser;}
  2670.     repeat
  2671.         if not HandleEvents then
  2672.             if info^.RoiShowing and (RoiUpdateTime < 30) then
  2673.                 DrawRoi;
  2674.         ShowInsertionPoint;
  2675.         SelectCursor;
  2676.         if Digitizing then begin
  2677.                 CaptureAndDisplayFrame;
  2678.                 if ContinuousHistogram then
  2679.                     ShowContinuousHistogram;
  2680.             end;
  2681.         if Finished then
  2682.             Shutdown;
  2683.     until finished;
  2684.     CloseSerialPorts;
  2685.     isOK := LoadCLUTResource(AppleDefaultCLUT);
  2686.     RestoreScreen; {Force Finder to redraw color icons}
  2687.   {FinalUserMacros;}
  2688. end.